Привет всем! Решил поделиться собственной поделкой, которую, будучи человеком с относительно кучерявыми руками(и без паяльника), сумел-таки изготовить. Получилось простое, но работающее и практически полезное устройство. Итак, вводная: не очень хорошо работающий котел в частном доме уже начавшийся отопительный сезон, который надо пройти с тем что есть, оперативно реагируя на отключение отопления ваш покорный слуга, практически без никаких навыков по железу В итоге, решил попробовать реанимировать свою же собственную, заброшенную, идею с контролем температуры отопления по SMS, собрав все на arduino с максимальным использованием готовых модулей и с минимальной работой руками. Состав "изделия" у меня получился следующим: Iskra Neo GRPS Shield светодиод зеленый пара резисторов (один в цепь к светодиоду на 220 Ом, второй, на 4.7кОм - к датчику температуры) датчик температуры DS18B20 макетная плата для соединения без пайки 3 одножильных провода "папа-мама", которые пошли на изготовление удлинителя для датчика температуры (единственное место где есть пайка) пищевой контейнер в качестве корпуса microUSB зарядка как блок питания несколько болтов с гайками м3 и капроновых стяжек для фиксации внутри корпуса искры с шилдом, макетной платы и кабеля от зарядки с удлинителем. Схема получилась примерно такая, с поправкой на то, что в реальном устройстве сверху устанавливается GPRS шилд, через который уже идут все соединения: Вид в сборе без крышки: Все максимально просто, на основе примеров по каждому компоненту. Датчик снимает температуру с батареи, зеленый светодиод мигает, сигнализируя о нормальной работе основного цикла программы.При наличии SMS запроса формируется ответ со снятой температурой, при падении температуры ниже 30 (если до этого она поднималась выше) посылается SMS с предупреждением на номер забитый в скетче. Скетч: Код (C++): #include <GPRS_Shield_Arduino.h> #include <sim900.h> #include <OneWire.h> #define DEBUG 1 #define ALERT_TEMP 30.0 #define ALERT_PHONE "___" #define ALERT_PHONE_2 "___" OneWire ds(10); GPRS gprs(Serial1); char _message[160]; char _phone[16]; char _datetime[24]; int alert_control = 0; void led_ok() { digitalWrite(12, HIGH); delay(1000); digitalWrite(12, LOW); } double get_term() { byte i; byte present = 0; byte type; byte data[12]; byte addr[8]; if (!ds.search(addr)) { if (DEBUG) Serial.println("No more adresses."); ds.reset_search(); delay(250); return 0.0; } if (DEBUG) { Serial.print("ROM ="); for (i = 0; i < 8; i++) { Serial.print(" "); Serial.print(addr[i], HEX); } Serial.println(""); } ds.reset(); ds.select(addr); ds.write(0x44); delay(1000); present = ds.reset(); ds.select(addr); ds.write(0xBE); if (DEBUG) { Serial.print("Data = "); Serial.print(present, HEX); Serial.print(" "); } for (i = 0; i < 9; i++) { data[i] = ds.read(); if (DEBUG) Serial.print(data[i], HEX); } if (DEBUG) Serial.println(""); int16_t raw = (data[1] << 8) | data[0]; byte cfg = (data[4] & 0x60); if (cfg == 0x00) { raw = raw & -7; } else if (cfg == 0x20) { raw = raw & -3; } else if (cfg == 0x40) { raw = raw & -1; } ds.reset_search(); double term = (double)raw / 16.0; if (DEBUG) { Serial.print("T="); Serial.println(term); } return term; } char* has_request_from() { if (gprs.ifSMSNow()) { delay(100); gprs.readSMS(_message, _phone, _datetime); if (DEBUG) { Serial.print("From number: "); Serial.println(_phone); Serial.print("Datetime: "); Serial.println(_datetime); Serial.print("Recieved Message: "); Serial.println(_message); } String s = String(_message); if (s == String("451")) { return _phone; } else { return 0; } } return 0; } void send_term(char *into, double term, int alert) { char term_str[10]; char message[12]; dtostrf(term,2,0,term_str); if (alert == 0) { sprintf(message, "T=%s", term_str); } else { sprintf(message, "AT=%s", term_str); } if (DEBUG) { Serial.print("Send SMS: "); Serial.print(message); Serial.println(""); } gprs.sendSMS(into, message); } void setup() { pinMode(12, OUTPUT); Serial1.begin(9600); if (DEBUG) Serial.println("Serial init OK"); gprs.powerOn(); while (!gprs.init()) { delay(1000); if (DEBUG) Serial.println("Init error"); } if (DEBUG) Serial.println("GPRS init success"); } void loop() { led_ok(); double term = get_term(); if (alert_control == 0 && term >= ALERT_TEMP) { alert_control = 1; } char* from = has_request_from(); if (from != 0) { if (DEBUG) { Serial.println("Send temperature!"); } send_term(from, term, 0); } if (alert_control == 1 && term < ALERT_TEMP) { alert_control = 0; send_term(ALERT_PHONE, term, 1); send_term(ALERT_PHONE_2, term, 1); } } В принципе, на этом этапе уже был весь нужный мне функционал и взаимодействовать можно было с любого телефона через SMS, отправляя "451" в тексте, но хотелось большего и была написана отдельная программка для Android, реализующая некий пользовательский интерфейс поверх все тех же SMS, номер телефона опрашиваемой симки при этом задается в настройках: Исходники прилагаю. В целом же, если не считать редких (раз в N недель) зависаний где-то на опросе GRPS шилда все работает достаточно стабильно и свою задачу по отслеживанию температуры отопления выполняет. В эксплуатации с начала ноября. В дальнейшем, можно расширить протокол, передавая другие параметры или подумать над источником бесперебойного питания для поделки, так как контроль за электричеством и циркуляционным насосом тоже представляет интерес, но для меня это будет уже следующим уровнем.
Ну что я могу сказать, отопительный сезон с этой поделкой пройден. Отключения котла отслеживались исправно. Единственную правку пришлось внести в клиента для смартфона, в классе MainActivity.java надо поменять местами строчки 78 и 79, чтобы получилось: sms.getText() .replace("AT=", "") .replace("T=", "") В целом же SMS транспорт показал себя не самым удачным и технологичным решением - вай-фай модуль и какой-нибудь самописный телеграмм бот, возможно, были бы лучше (хоть и с дополнительной зависимостью от ростелекома с роскомнадзором).
Эммм... http://forum.amperka.ru/threads/Контроль-работы-газового-электрического-твердотельного-котла.17310/
В рамках работы над v2, играюсь с искрой жс, сделал работающий в наших условиях класс для телеграм бота Код (Javascript): function Telegram(_http, _proxyList, _botName, _botToken, _resetOnError) { var http = _http; var proxyList = _proxyList; var botName = _botName; var botToken = _botToken; var self = this; this.lastUpdateId = null; this.invokeGet = function(url, onData, onError, proxyIndex) { var i = Math.round(Math.random() * (proxyList.length - 1)); if (proxyIndex) { i = proxyIndex; } var host = proxyList[i].split(":")[0]; var port = proxyList[i].split(":")[1]; console.log("Use proxy " + host + ":" + port); var options = { host: host, protocol: "https", port: port, path: url, method: "GET", }; http.get(options, function(res) { var contents = ""; res.on('data', function(data) { contents += data; }); res.on('close', function() { onData(contents, i); }); }); }; this.sendMessage = function(chatId, text, proxyIndex) { self.invokeGet( "https://api.telegram.org/bot" + botToken + "/sendMessage?chat_id=" + chatId + "&text=" + text, function(data) { console.log("Message sent:" + text); }, function(error) { }, proxyIndex ); }; this.readMessages = function() { self.invokeGet( "https://api.telegram.org/bot" + botToken + "/getUpdates" + (self.lastUpdateId ? "?offset=" + (self.lastUpdateId + 1) : ""), function(data, proxyIndex) { //console.log("Messages: " + data); var res = JSON.parse(data); self.onMessage(self, res, proxyIndex); }, function(error) { console.log(error); } ); }; this.onMessage = function(self, data, proxyIndex) {}; this.invokeGet( "https://api.telegram.org/bot" + botToken + "/getMe", function(data) { var res = JSON.parse(data); if (res.result.first_name == botName) { console.log("Bot found: " + res.result.first_name); setInterval(self.readMessages, 5 * 1000); } }, function (error) { setTimeout(function() { if (_resetOnError) { reset(); load(); } }, 5 * 1000); } ); } Пример использования в варианте эхо бота, не работает кирилица в уникоде Код (Javascript): ... var telegram = new Telegram(http, proxyList, botName, botToken, true); telegram.onMessage = function(self, data, proxyIndex) { for (var i in data.result) { var m = data.result[i]; var chatId = m.message.chat.id; var from = m.message.from.first_name + " " + m.message.from.last_name; var text = m.message.text; console.log("Chat:" + chatId); console.log("From: " + from); console.log("Text: " + text); self.lastUpdateId = m.update_id; console.log("UpdateId:" + self.lastUpdateId); self.sendMessage(chatId, "->" + text, proxyIndex); } }; Список проксей можно наполнить поковырявшись в списках "free proxy", выбирая те, которые работают поверх http/https (URL целевого ресурса передается в HTTP запросе). 10-ок пригодных за час легко можно нацыганить.