Отправка и получение SMS через X-Control Dispatcher

Всем привет! Продолжаю пиарить свою систему)))
Теперь покажу как отправлять и принимать SMS.

Техзадание

Несколько месяцев назад я написал вот этот пост we.easyelectronics.ru/MrMisha/sozdanie-avtomatizirovanoy-sistemy-na-baze-x-control-dispatcher.html, в котором подробно описано, как интегрировать самопальный USB-термометр в данную программу. В результате температура и состояние двух его каналов выводилось на вот такой виджет:

Галочка и кнопка использовались для управления этими двумя каналами.
Теперь сделаем так, чтобы температуру и состояние каналов можно было запрашивать по SMS, ну и соответственно, рулить каналами тоже по SMS.

Аппаратная часть

Конечно же, есть всякие сервисы для отправки SMS, но я их даже не рассматривал. Отправлять SMS будем через любой GSM модем, с которым можно общаться через AT команды. Это может быть SIM900 или какой-то USB-модем.
Допустим, модем Вы подключили, ну и в случае с SIM*** запустили.

Программная часть

Качаем здесь последнюю версию проги (при обновлении версии ссылка меняется).
Предполагаю, что у Вас уже есть виджет, в который устанавливается температура (в самой первый ссылке описано).
Качаем расширение для работы с AT-модемами bitbucket.org/x-ctrl/x-control-dispatcher/downloads/AT%20modem.rar (желательно почитать ReadMe.txt). Копируем modules_lib в папку с программой и запускаем саму прогу. Переходим на вкладку «Модули» и добавляем модуль «AT_modem». На вкладке этого модуля открываем вкладку «Опции»:

Здесь всё интуитивно понятно. Единственное, что нужно сделать — это настроить порт. Если у Вас usb-модем, то нужно просто выбрать порт (у меня COM9), если что-то, что физически подключается через COM, тогда нужно задать битрейт и т.д.
После того, как модем будет найден, в окне «Состояние» будет указано «Подключен».
Перейдем на вкладку «Компоненты»:

В ReadMe.txt описано их значение, но уже копирну и сюда:
conn_state. Состояние соединения (bool)
  • sq. Уровень сигнала.
  • net_name. Название сети, в которой зарегистрирован модем.
  • sms_rec_text. Полученый текст SMS.
  • sms_rec_phone. Номер абонента, от которого пришло SMS.
  • sms_send_text. Текст SMS для отправки.
  • sms_send_phone. Номер абонента для отправки SMS.
Когда приходит SMS, сначала устанавливается текст в sms_rec_text, а затем номер отправителя в sms_rec_phone.
Чтобы отправить SMS, сначала нужно установить текст в sms_send_text, а затем номер в sms_send_phone, после чего будет произведена отправка SMS указаному абоненту.
Конечно же, взаимодействие этих компонентов с остальными функциями проги происходит через компоненты стандартных виджетов. Добавляем стандартный виджет и создаем на нем вот такие компоненты (красной стрелкой указан виджет, дополнительное настройки которого вызваны):

Чтобы Вам не создавать и не настраивать все эти компоненты, я сохранил их в комплект (в архиве файл gsm_kit.swkit). Создаем новый виджет (назовем его «phone»), открываем его дополнительные настройки, жмем «Загрузить с комплекта», выбираем этот файл, префикс оставляем пустым, затем «ОК» или «Применить». Виджет готов, подключаем его к модулю. Окно компонентов модуля должно выглядеть вот так:


Итак, теперь, когда придет SMS, его текст будет записан в компонент rec_text, а номер отправителя в rec_phone. Чтобы отправить sms, надо сначала записать в компонент виджета send_text текст сообщения, а затем, в send_phone номер телефона, на который нужно отправлять.
Обрабатывать принятые сообщения будем скриптом. Советую почитать Создание скриптов для X-Control Dispatcher .
Создаем новый скрипт и подключаем к этому виджету (в дополнительных настройках). Пока что его содержимое будет таким:
// получаем компоненты для работы с модемом
var rec = {
	phone: XObj.getComponent("rec_phone"),
	text: XObj.getComponent("rec_text")
}
var send = {
	phone: XObj.getComponent("send_phone"),
	text: XObj.getComponent("send_text")
}

XObj.allLoaded.connect(this, function() {

	// После получения SMS, сначала записывается текст в rec_text, а затем номер в rec_phone.
	// Подключаемся к rec_phone, чтобы вызов функции был в тот момент, когда установлен и текст, и номер.
	rec.phone.valueUpdated.connect(this, function() {
		var	inText = rec.text.getValue();	// читаем входящий текст
		var	inPhone = rec.phone.getValue();	// читаем номер		
		
		var	sendSms = parseSMS(inText);	// текст для отправки sms
		
		if (sendSms.length) {
			// Если нужно что-то отправлять, устанавливаем текст, а затем номер абонента, который прислал SMS
			send.text.setValue(sendSms, XObj);
			send.phone.setValue(inPhone, XObj);
		}
	});
	
});

// Функция обработки входящего сообщения. Возвращает ответ (если он есть)
function parseSMS(text) {
	// Если нам прислали "привет!", отвечаем "Здравствуй!"
	if (text == "привет!") return "Здравствуй!";	
	
	return "";
}

Теперь если кто проге напишет «привет!», она ответит «Здравствуй!».

Итак, давайте определимся, какими командами будем общаться с программой. Сделаем так:
Для управления каналом1 к тексте должно быть к1=<0/1>, аналогично для канала 2. К примеру, включить канал1: к1=1. Чтобы в ответ мы получили состояние каналов и температуру, в конце SMS должен быть знак вопроса. Чтобы выключить канал1, включить канал2 и запросить ответное SMS, мы должны отправить «к1=0 к2=1 ?». Если просто надо запросить состояние, то в тексте должен быть только знак вопроса.
Добавляем в скрипт (можно в конец):
// объект для работы с термометром
var thermometer = {
	// Компоненты термометра находятся на другом виджете, который может быть загружен после этого, 
	// из-за чего получить его компоненты сразу мы не можем. 
	// Поэтому, получение этих компонентов будет по сигналу standartWidgetsLoaded (когда все виджеты загружены)
	ch1: undefined,
	ch2: undefined,
	t: undefined,
	
	setChannel: function (n, s) {
		if (n == 1) this.ch1.setValue(s, XObj);
		if (n == 2) this.ch2.setValue(s, XObj);
	},
	getChannel: function (n) {
		if (n == 1) return this.ch1.getValue();
		if (n == 2) return this.ch2.getValue();
	},
	getT: function () {
		return parseInt(this.t.lastSetValue());
	}
}
XObj.standartWidgetsLoaded.connect(this, function() {
	var	tWidget = XObj.getOtherWidget("thermometer");	// получаем виджет термометра
	thermometer.ch1 = tWidget.getComponent("ch1");
	thermometer.ch2 = tWidget.getComponent("ch2");
	thermometer.t = tWidget.getComponent("arrow");
});

Теперь у нас есть функции для получения температуры, установки и получения состояния каналов.
Изменяем функцию parseSMS:
function parseSMS(text) {
	// Если нам прислали "привет!", отвечаем "Здравствуй!"
	if (text == "привет!") return "Здравствуй!";
	
	// если в строке есть "к1="
	var	index = text.indexOf("к1=");
	if (index > -1) {
		var	s = text[index+3];	// берем символ, который после "к1="
		// если значение 0 или 1, устанавливаем канал
		if (s == '0') thermometer.setChannel(1, false);
		else if (s == '1') thermometer.setChannel(1, true);
	}
	// то же самое для "к2="
	index = text.indexOf("к2=");
	if (index > -1) {
		var	s = text[index+3];
		if (s == '0') thermometer.setChannel(2, false);
		else if (s == '1') thermometer.setChannel(2, true);
	}
	
	// Если запрос состояния
	if (text[text.length-1] == '?') {
		return	str = "Температура = " + thermometer.getT() + ", " +
				"канал 1 = " + (thermometer.getChannel(1) ? "вкл" : "выкл") + ", " +
				"канал 2 = " + (thermometer.getChannel(2) ? "вкл" : "выкл");		
	}
	
	return "";
}


Стоит отметить, что на вкладке модуля есть вкладка «Отладка», в которую выводится информация о полученных, отправленных, не отправленных SMS.

Завершение

Исходники этого расширения можно скачать здесь. Там, кстати, Вы можете посмотреть, как отправлять и получать SMS кирилицей (в инете по этому мало инфы)
  • +1
  • 04 ноября 2015, 19:50
  • MrMisha
  • 1
Файлы в топике: gsm_kit.zip

Комментарии (1)

RSS свернуть / развернуть
Там, кстати, Вы можете посмотреть, как отправлять и получать SMS кирилицей (в инете по этому мало инфы)
Там, если я не ошибаюсь, вместо ASCII кода символ=байт идёт Unicode
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.