new Modules from Chat

This commit is contained in:
Mit4el
2025-07-25 00:23:37 +03:00
parent acf7732c3c
commit 18012bd57a
24 changed files with 6283 additions and 1279 deletions

View File

@@ -0,0 +1,579 @@
// Licensed under the Cooperative Non-Violent Public License (CNPL)
// See: https://github.com/CHE77/IoTManager-Modules/blob/main/LICENSE
#define MQTT_MAX_PACKET_SIZE 512 // или 1024
#include "Global.h"
#include "classes/IoTItem.h"
#include <math.h>
#define EARTH_RADIUS_KM 6371.0 // Радиус Земли в километрах
#include "NTP.h"
#include <PubSubClient.h> // чтобы знать тип
extern PubSubClient mqtt; // объявляем глобальный объект
class Presence : public IoTItem
{
private:
String _MAC;
String _parameter;
IoTItem *tmp;
int _minutesPassed = 0;
String json = "{}";
int orange = 0;
int red = 0;
int offline = 0;
bool dataFromNode = false;
String _topic = "";
bool _isJson;
bool _ticker = true;
bool _debug = false;
bool sendOk = false;
float _lat_A = 0;
float _lon_A = 0;
struct PresenceData
{
String chargingState;
String plugState;
String connectedWifi;
String geoLocation;
float lat = 0.0;
float lon = 0.0;
unsigned long geoTimestamp = 0;
String geoTime;
String deviceName;
int batteryLevel = -1;
unsigned long currentTimestamp = 0;
String currentTime;
unsigned long nextScheduledTimestamp = 0;
String nextScheduledTime;
unsigned long nextAlarmclockTimestamp = 0;
String nextAlarmclockTime;
std::vector<String> conditionContent;
String conditionContentString;
};
PresenceData pdata;
public:
Presence(String parameters) : IoTItem(parameters)
{
_parameter = jsonReadStr(parameters, "parameter");
jsonRead(parameters, F("orange"), orange);
jsonRead(parameters, F("red"), red);
jsonRead(parameters, F("offline"), offline);
_topic = jsonReadStr(parameters, "topic");
if (_debug)
SerialPrint("i", "Presence topic : ", _topic);
jsonRead(parameters, F("isJson"), _isJson);
// jsonRead(parameters, "addPrefix", _addPrefix);
jsonRead(parameters, F("Lat. A"), _lat_A);
jsonRead(parameters, F("Long. A"), _lon_A);
jsonRead(parameters, F("ticker"), _ticker);
jsonRead(parameters, F("debug"), _debug);
dataFromNode = false;
if (mqttIsConnect())
{
mqtt.setBufferSize(512);
sendOk = true;
mqttSubscribeExternal(_topic);
}
}
char *TimeToString(unsigned long t)
{
static char str[12];
long h = t / 3600;
t = t % 3600;
int m = t / 60;
int s = t % 60;
sprintf(str, "%02ld:%02d:%02d", h, m, s);
return str;
}
double toRadians(double degrees)
{
return degrees * M_PI / 180.0;
}
double toDegrees(double radians)
{
return radians * 180.0 / M_PI;
}
// Возвращает пеленг в градусах: от 0 до 360
double calculateInitialBearing(double lat1, double lon1, double lat2, double lon2)
{
lat1 = toRadians(lat1);
lon1 = toRadians(lon1);
lat2 = toRadians(lat2);
lon2 = toRadians(lon2);
double deltaLon = lon2 - lon1;
double y = sin(deltaLon) * cos(lat2);
double x = cos(lat1) * sin(lat2) -
sin(lat1) * cos(lat2) * cos(deltaLon);
double bearing = atan2(y, x);
bearing = toDegrees(bearing);
// Приводим к диапазону 0360
return fmod((bearing + 360.0), 360.0);
}
// lat и lon — в градусах
double haversineDistance(double lat1, double lon1, double lat2, double lon2)
{
double dLat = toRadians(lat2 - lat1);
double dLon = toRadians(lon2 - lon1);
lat1 = toRadians(lat1);
lat2 = toRadians(lat2);
double a = sin(dLat / 2) * sin(dLat / 2) +
cos(lat1) * cos(lat2) *
sin(dLon / 2) * sin(dLon / 2);
double c = 2 * atan2(sqrt(a), sqrt(1 - a));
return EARTH_RADIUS_KM * c * 1000.0;
}
void onMqttRecive(String &topic, String &msg)
{
Serial.printf("[MQTT] Topic: %s\nPayload size: %d bytes\n", topic.c_str(), msg.length());
msg.trim(); // Убираем пробелы и переносы строк
if (msg.indexOf("HELLO") == -1)
{
if (_debug)
SerialPrint("i", "Presence HELLO", " _1d: " + _id + " topic: " + topic + " msg: " + msg);
String dev = selectToMarkerLast(topic, "/");
dev.toUpperCase();
dev.replace(":", "");
if (_topic != topic)
{
if (_debug)
{
SerialPrint("i", "Presence", topic + " not equal: " + _topic + " msg: " + msg);
}
return;
}
if (_isJson)
{
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
DeserializationError err = deserializeJson(doc, msg);
if (err)
{
SerialPrint("E", F("Presence"), err.f_str());
return;
}
JsonObject obj = doc.as<JsonObject>();
if (obj.containsKey("chargingState"))
{
pdata.chargingState = obj["chargingState"].as<String>();
}
if (obj.containsKey("plugState"))
{
pdata.plugState = obj["plugState"].as<String>();
}
if (obj.containsKey("connectedWifi"))
pdata.connectedWifi = obj["connectedWifi"].as<String>();
if (obj.containsKey("geoLocation"))
{
pdata.geoLocation = obj["geoLocation"].as<String>();
// Разбор геолокации после получения
parseGeo(pdata.geoLocation);
pdata.geoTime = getDateTimeDotFormatedFromUnix(pdata.geoTimestamp);
SerialPrint("i", "Presence", "GeoTime : " + pdata.geoTime);
}
if (obj.containsKey("deviceName"))
pdata.deviceName = obj["deviceName"].as<String>();
if (obj.containsKey("batteryLevel"))
pdata.batteryLevel = obj["batteryLevel"].as<int>();
if (obj.containsKey("currentTimestamp"))
{
pdata.currentTimestamp = obj["currentTimestamp"].as<unsigned long>();
pdata.currentTime = getDateTimeDotFormatedFromUnix(pdata.currentTimestamp);
}
if (obj.containsKey("nextScheduledTimestamp"))
{
pdata.nextScheduledTimestamp = obj["nextScheduledTimestamp"].as<unsigned long>();
pdata.nextScheduledTime = getDateTimeDotFormatedFromUnix(pdata.nextScheduledTimestamp);
}
if (obj.containsKey("nextAlarmclockTimestamp"))
{
pdata.nextAlarmclockTimestamp = obj["nextAlarmclockTimestamp"].as<unsigned long>();
pdata.nextAlarmclockTime = getDateTimeDotFormatedFromUnix(pdata.nextAlarmclockTimestamp);
}
if (obj.containsKey("conditionContent"))
{
JsonArray arr = obj["conditionContent"].as<JsonArray>();
pdata.conditionContent.clear();
for (String s : arr)
{
pdata.conditionContent.push_back(s);
}
String conditionStr;
for (size_t i = 0; i < pdata.conditionContent.size(); ++i)
{
conditionStr += pdata.conditionContent[i];
if (i < pdata.conditionContent.size() - 1)
conditionStr += ", ";
}
pdata.conditionContentString = conditionStr;
}
dataFromNode = true;
_minutesPassed = 0;
String sensorVal;
if (_parameter == "latitude")
{
value.isDecimal = true;
value.valD = pdata.lat;
}
else if (_parameter == "longitude")
{
value.isDecimal = true;
value.valD = pdata.lon;
}
else if (_parameter == "azimuth")
{
value.isDecimal = true;
value.valD = calculateInitialBearing(_lat_A, _lon_A, pdata.lat, pdata.lon);
}
else if (_parameter == "distance")
{
value.isDecimal = true;
value.valD = haversineDistance(_lat_A, _lon_A, pdata.lat, pdata.lon);
}
else if (_parameter == "batteryLevel")
{
value.isDecimal = true;
value.valD = pdata.batteryLevel;
}
else if (_parameter == "geoTime")
{
value.isDecimal = false;
value.valS = pdata.geoTime;
}
else if (_parameter == "geoTimestamp")
{
value.isDecimal = false;
value.valS = pdata.geoTimestamp;
}
else if (_parameter == "currentTime")
{
value.isDecimal = false;
value.valS = pdata.currentTime;
}
else if (_parameter == "nextScheduledTime")
{
value.isDecimal = false;
value.valS = pdata.nextScheduledTime;
}
else if (_parameter == "nextAlarmclockTime")
{
value.isDecimal = false;
value.valS = pdata.nextAlarmclockTime;
}
else if (_parameter == "conditionContent")
{
value.isDecimal = false;
value.valS = pdata.conditionContentString;
}
else if (obj.containsKey(_parameter) && obj[_parameter].is<const char *>())
{
sensorVal = obj[_parameter].as<const char *>();
value.isDecimal = false;
value.valS = sensorVal;
}
else
{
value.isDecimal = false;
value.valS = "parameter mismatch";
}
if (value.isDecimal)
{
regEvent(value.valD, F("Presence"), _debug, _ticker);
}
else
{
regEvent(value.valS, F("Presence"), _debug, _ticker);
}
}
else
{
if (_debug)
{
SerialPrint("i", "Presence", "Received MAC: " + dev + " val=" + msg);
}
dataFromNode = true;
_minutesPassed = 0;
setValue(msg);
}
}
}
IoTValue execute(String command, std::vector<IoTValue> &param)
{
IoTValue valTmp;
if (command == "latitude")
{
valTmp.isDecimal = true;
valTmp.valD = pdata.lat;
return valTmp;
}
else if (command == "longitude")
{
valTmp.isDecimal = true;
valTmp.valD = pdata.lon;
return valTmp;
}
else if (command == "azimuth")
{
if (param.size() == 2 && param[0].isDecimal && param[1].isDecimal)
{
valTmp.isDecimal = true;
valTmp.valD = calculateInitialBearing(param[0].valD, param[1].valD, pdata.lat, pdata.lon);
}
else
{
valTmp.isDecimal = false;
valTmp.valS = "wrong parameters";
}
return valTmp;
}
else if (command == "distance")
{
if (param.size() == 2 && param[1].isDecimal && param[1].isDecimal)
{
valTmp.isDecimal = true;
valTmp.valD = haversineDistance(param[0].valD, param[1].valD, pdata.lat, pdata.lon);
}
else
{
valTmp.isDecimal = false;
valTmp.valS = "wrong parameters";
}
return valTmp;
}
else if (command == "batteryLevel")
{
valTmp.isDecimal = true;
valTmp.valD = pdata.batteryLevel;
return valTmp;
}
else if (command == "geoTime")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.geoTime;
return valTmp;
}
else if (command == "geoTimestamp")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.geoTimestamp;
return valTmp;
}
else if (command == "currentTime")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.currentTime;
return valTmp;
}
else if (command == "currentTimestamp")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.currentTimestamp;
return valTmp;
}
else if (command == "nextScheduledTime")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.nextScheduledTime;
return valTmp;
}
else if (command == "nextScheduledTimestamp")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.nextScheduledTimestamp;
return valTmp;
}
else if (command == "nextAlarmclockTime")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.nextAlarmclockTime;
return valTmp;
}
else if (command == "nextAlarmclockTimestamp")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.nextAlarmclockTimestamp;
return valTmp;
}
else if (command == "conditionContent")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.conditionContentString;
return valTmp;
}
else if (command == "chargingState")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.chargingState;
return valTmp;
}
else if (command == "plugState")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.plugState;
return valTmp;
}
else if (command == "connectedWifi")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.connectedWifi;
return valTmp;
}
else if (command == "deviceName")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.deviceName;
return valTmp;
}
else if (command == "geoLocation")
{
valTmp.isDecimal = false;
valTmp.valS = pdata.geoLocation;
return valTmp;
}
else
{
valTmp.isDecimal = false;
valTmp.valS = "wrong command";
return valTmp;
}
return {};
}
String getMqttExterSub()
{
return _topic;
}
void doByInterval()
{
_minutesPassed++;
setNewWidgetAttributes();
if (mqttIsConnect() && !sendOk)
{
mqtt.setBufferSize(512); // ← ДО подписи
sendOk = true;
mqttSubscribeExternal(_topic);
}
}
void onMqttWsAppConnectEvent()
{
setNewWidgetAttributes();
}
void setNewWidgetAttributes()
{
jsonWriteStr(json, F("info"), prettyMinutsTimeout(_minutesPassed));
if (dataFromNode)
{
if (orange != 0 && red != 0 && offline != 0)
{
if (_minutesPassed < orange)
{
jsonWriteStr(json, F("color"), "");
}
if (_minutesPassed >= orange && _minutesPassed < red)
{
jsonWriteStr(json, F("color"), F("orange")); // сделаем виджет оранжевым
}
if (_minutesPassed >= red && _minutesPassed < offline)
{
jsonWriteStr(json, F("color"), F("red")); // сделаем виджет красным
}
if (_minutesPassed >= offline)
{
jsonWriteStr(json, F("info"), F("offline"));
SerialPrint("i", "Presence", _id + " - offline");
}
}
}
else
{
jsonWriteStr(json, F("info"), F("awaiting"));
}
// SerialPrint("i", "JSON", json);
sendSubWidgetsValues(_id, json);
}
void parseGeo(const String &geo)
{
if (!geo.startsWith("geo:"))
return;
int commaIndex = geo.indexOf(',', 4);
int semicolonIndex = geo.indexOf(';', commaIndex);
if (commaIndex == -1 || semicolonIndex == -1)
return;
String latStr = geo.substring(4, commaIndex);
String lonStr = geo.substring(commaIndex + 1, semicolonIndex);
// timestamp
String tsTag = "timestamp=";
int tsIndex = geo.indexOf(tsTag);
String tsStr = (tsIndex > 0) ? geo.substring(tsIndex + tsTag.length()) : "";
pdata.lat = latStr.toFloat();
pdata.lon = lonStr.toFloat();
pdata.geoTimestamp = tsStr.toInt();
if (_debug)
{
SerialPrint("i", "Presence", "Lat: " + String(pdata.lat, 6));
SerialPrint("i", "Presence", "Lon: " + String(pdata.lon, 6));
SerialPrint("i", "Presence", "Geo timestamp: " + String(pdata.geoTimestamp));
}
}
~Presence() {};
};
void *getAPI_Presence(String subtype, String param)
{
if (subtype == F("Presence"))
{
return new Presence(param);
}
else
{
return nullptr;
}
}

View File

@@ -0,0 +1,372 @@
{
"mark": "iotm",
"config": [
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutDistance",
"needSave": 0,
"widget": "anydataKm",
"page": "Output",
"descr": "Distance",
"int": "0",
"val": "0.0",
"map": "",
"plus": 0,
"multiply": "0.001",
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutAzimuth",
"needSave": 0,
"widget": "anydataСorner",
"page": "Output",
"descr": "Azimuth",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Presence",
"id": "presence",
"widget": "anydataM",
"page": "Presence",
"descr": "Distance",
"Lat. A": "47.0159",
"Long. A": "28.8448",
"parameter": "distance",
"topic": "/myPhone/status",
"isJson": 1,
"round": "0",
"orange": 60,
"red": 120,
"offline": 180,
"int": 15,
"ticker": 1,
"debug": 1,
"moduleName": "Presence"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutLat",
"needSave": 0,
"widget": "anydataСorner",
"page": "Output",
"descr": "Latitude",
"int": "0",
"val": "0.0",
"map": "",
"plus": 0,
"multiply": 1,
"round": "1",
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutLong",
"needSave": 0,
"widget": "anydataСorner",
"page": "Output",
"descr": "Longitude",
"int": "0",
"val": "0.0",
"map": "",
"plus": 0,
"multiply": 1,
"round": "1",
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutbatteryLevel",
"needSave": 0,
"widget": "anydataHum",
"page": "Output",
"descr": "batteryLevel",
"int": "0",
"val": "0.0",
"map": "",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutgeoTime",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "geoTime",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutgeoTimestamp",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "geoTimestamp",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutcurrentTime",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "currentTime",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutcurrentTimestamp",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "currentTimestamp",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutnextScheduledTime",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "nextScheduledTime",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutnextScheduledTimestamp",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "nextScheduledTimestamp",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutnextAlarmclockTime",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "nextAlarmclockTime",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutnextAlarmclockTimestamp",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "nextAlarmclockTimestamp",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutchargingState",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "chargingState",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutplugState",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "plugState",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutconnectedWifi",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "connectedWifi",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutdeviceName",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "deviceName",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutgeoLocation",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "geoLocation",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
},
{
"global": 0,
"type": "Reading",
"subtype": "Variable",
"id": "voutconditionContent",
"needSave": 0,
"widget": "anydataDef",
"page": "Output",
"descr": "conditionContent",
"int": "0",
"val": "0.0",
"map": "1024,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 0,
"moduleName": "Variable"
}
]
}
scenario=> if presence then {
voutDistance = presence.distance(47.0159,28.8448)
voutAzimuth = presence.azimuth(47.0159,28.8448)
voutLat = presence.latitude()
voutLong = presence.longitude()
voutbatteryLevel = presence.batteryLevel()
voutgeoTime = presence.geoTime()
voutgeoTimestamp = presence.geoTimestamp()
voutcurrentTime = presence.currentTime()
voutcurrentTimestamp = presence.currentTimestamp()
voutnextScheduledTime = presence.nextScheduledTime()
voutnextScheduledTimestamp = presence.nextScheduledTimestamp()
voutnextAlarmclockTime = presence.nextAlarmclockTime()
voutnextAlarmclockTimestamp = presence.nextAlarmclockTimestamp()
voutchargingState = presence.chargingState()
voutplugState = presence.plugState()
voutconnectedWifi = presence.connectedWifi()
voutdeviceName = presence.deviceName()
voutgeoLocation = presence.geoLocation()
voutconditionContent = presence.conditionContent()
}

View File

@@ -0,0 +1,199 @@
{
"menuSection": "sensors",
"configItem": [
{
"global": 0,
"name": "MQTT Presence Subscriber",
"type": "Reading",
"subtype": "Presence",
"id": "presence",
"widget": "anydataM",
"page": "Presence",
"descr": "Дистанция",
"Lat. A": "47.0159",
"Long. A": "28.8448",
"parameter": "distance",
"topic": "/myPhone/status",
"isJson": 1,
"round": "0",
"orange": 60,
"red": 120,
"offline": 180,
"int": 15,
"ticker": 1,
"debug": 1
}
],
"about": {
"authorName": "Alex",
"authorContact": "https://t.me/cmche",
"authorGit": "https://github.com/CHE77/IoTManager-Modules",
"exampleURL": "https://iotmanager.org/wiki",
"specialThanks": "",
"moduleName": "Presence",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"title": "MQTT Presence Subscriber",
"moduleDesc": "Модуль получения и обработки данных из Presence Publisher app - https://f-droid.org/packages/org.ostrya.presencepublisher/ https://play.google.com/store/apps/details?id=org.ostrya.presencepublisher Получает геопозицию телефона, считает пеленг и дистанцию.",
"license": "Cooperative Non-Violent Public License (CNPL)",
"propInfo": {
"Lat. A": "Широта точки отсчета (локации), в градусах",
"Long. A": "Долгота точки отсчета (локации), в градусах",
"parameter": "Параметр/ключ для получения данных из json и его производных. Совпадают с методами для сценария",
"topic": "Топик на который подписывется модуль. Должен совпадать с топиком в приложении и оканчиваться на status",
"isJson": "1 - ожидаем в топике json. Другие форматы пока не подерживаются. В приложении выберите тоже json",
"round": "Округление после запятой.",
"orange": "Количество минут после которого окрасить виджет в оранжевый цвет",
"red": "количество минут после которого окрасить виджет в красный цвет",
"offline": "Количество минут после которого отобразить что устройство offline, если все три orange red и offline поставить в ноль - то функция окраски выключится",
"int": "Интервал для изменения цвета",
"ticker": "Генерировать(1) или нет(0) события при каждом тике часов (каждые int секунд).",
"debug": "1 - выводить дополнительный лог в сериал"
},
"retInfo": " - Согласно выбраного параметра",
"funcInfo": [
{
"name": "latitude",
"descr": "Получить широту позиции устройства (и далее) с приложением Presence Publisher",
"params": [
"presence.latitude()"
]
},
{
"name": "longitude",
"descr": "Получить долготу позиции устройства",
"params": [
"presence.longitude()"
]
},
{
"name": "distance",
"descr": "Получить дистанцию до устройства",
"params": [
"presence.distance()"
]
},
{
"name": "azimuth",
"descr": "Получить пеленг на устройтво",
"params": [
"presence.azimuth()"
]
},
{
"name": "batteryLevel",
"descr": "Получить уровень заряда батареи устройства",
"params": [
"presence.batteryLevel()"
]
},
{
"name": "geoTime",
"descr": "Получить время определения геопозии устройства",
"params": [
"presence.geoTime()"
]
},
{
"name": "geoTimestamp",
"descr": "Получить UnixTime определения геопозии устройства",
"params": [
"presence.geoTimestamp()"
]
},
{
"name": "currentTime",
"descr": "Получить время получения геопозиции от устройства",
"params": [
"presence.currentTime()"
]
},
{
"name": "currentTimestamp",
"descr": "Получить UnixTime получения геопозиции от устройства",
"params": [
"presence.currentTimestamp()"
]
},
{
"name": "nextScheduledTime",
"descr": "Получить время следующего получения геопозиции от устройства",
"params": [
"presence.nextScheduledTime()"
]
},
{
"name": "nextScheduledTimestamp",
"descr": "Получить UnixTime следующего получения геопозиции от устройства",
"params": [
"presence.nextScheduledTimestamp()"
]
},
{
"name": "nextAlarmclockTime",
"descr": "Получить время следующего будильника на устройтве",
"params": [
"presence.nextAlarmclockTime()"
]
},
{
"name": "nextAlarmclockTimestamp",
"descr": "Получить UnixTime следующего будильника на устройтве",
"params": [
"presence.nextAlarmclockTimestamp()"
]
},
{
"name": "chargingState",
"descr": "Получить статус зарядки устройства",
"params": [
"presence.chargingState()"
]
},
{
"name": "plugState",
"descr": "Получить тип зарядки устройства",
"params": [
"presence.plugState()"
]
},
{
"name": "connectedWifi",
"descr": "Получить Wi-Fi точку доступа к которой подключено устройство",
"params": [
"presence.connectedWifi()"
]
},
{
"name": "deviceName",
"descr": "Получить имя устройства",
"params": [
"presence.deviceName()"
]
},
{
"name": "geoLocation",
"descr": "Получить строку с широтой, долготой и верменем определения геопозиции",
"params": [
"presence.geoLocation()"
]
},
{
"name": "conditionContent",
"descr": "Получить дополнительное условие отправки данных (геопозиции и др)",
"params": [
"presence.conditionContent()"
]
}
]
},
"defActive": false,
"usedLibs": {
"esp32*": [],
"esp82*": [],
"bk72*": []
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -0,0 +1,383 @@
[
{
"name": "anydataRed",
"label": "Сообщение1",
"widget": "anydata",
"icon": "body",
"color": "red",
"descrColor": "red"
},
{
"name": "anydataDgr",
"label": "Сообщение2",
"widget": "anydata",
"after": "",
"color": "red",
"icon": "walk"
},
{
"name": "anydataDef",
"label": "Текст",
"widget": "anydata",
"after": "",
"icon": ""
},
{
"name": "anydataVlt",
"label": "Вольты",
"widget": "anydata",
"after": "V",
"icon": "speedometer"
},
{
"name": "anydataAmp",
"label": "Амперы",
"widget": "anydata",
"after": "A",
"icon": "speedometer"
},
{
"name": "anydataWt",
"label": "Ватты",
"widget": "anydata",
"after": "Wt",
"icon": "speedometer",
"color": [
{
"level": 0,
"value": ""
},
{
"level": 200,
"value": "#009933"
},
{
"level": 2000,
"value": "#FF9900"
},
{
"level": 4000,
"value": "red"
}
]
},
{
"name": "anydataWth",
"label": "Энергия",
"widget": "anydata",
"after": "kWh",
"icon": "speedometer"
},
{
"name": "anydataHtz",
"label": "Герцы",
"widget": "anydata",
"after": "Hz",
"icon": "speedometer"
},
{
"name": "anydataTmp",
"label": "Температура",
"widget": "anydata",
"after": "°С",
"icon": "thermometer",
"font": "OCR A Std",
"color": [
{
"level": -20,
"value": "#0000CC"
},
{
"level": -10,
"value": "#0000CC"
},
{
"level": 0,
"value": "#0000CC"
},
{
"level": 12,
"value": "#3366FF"
},
{
"level": 16,
"value": "#33CCFF"
},
{
"level": 18,
"value": "#009933"
},
{
"level": 30,
"value": "#FF9900"
},
{
"level": 40,
"value": "red"
}
]
},
{
"name": "anydataMm",
"label": "Давление",
"widget": "anydata",
"after": "mm",
"icon": "speedometer"
},
{
"name": "anydataHum",
"label": "Влажность",
"widget": "anydata",
"after": "%",
"icon": "water",
"color": "#88AADF"
},
{
"name": "anydataTm",
"label": "Время",
"widget": "anydata",
"after": "",
"icon": "speedometer"
},
{
"name": "button",
"label": "Кнопка",
"widget": "btn",
"size": "large",
"color": "green",
"send": "test"
},
{
"name": "toggle",
"label": "Переключатель",
"widget": "toggle",
"icon": "",
"iconOff": ""
},
{
"name": "chart1",
"label": "График без точек",
"widget": "chart",
"dateFormat": "HH:mm",
"maxCount": 86400,
"pointRadius": 0
},
{
"name": "chart2",
"label": "График с точками",
"widget": "chart",
"maxCount": 86400,
"dateFormat": "HH:mm"
},
{
"name": "chart3",
"label": "График Дневной",
"widget": "chart",
"dateFormat": "DD.MM.YYYY",
"maxCount": 86400,
"type": "bar"
},
{
"name": "chart4",
"label": "График Часовой",
"widget": "chart",
"dateFormat": "HH:mm",
"maxCount": 3600,
"type": "bar"
},
{
"name": "chart5",
"label": "График двойной",
"widget": "chart",
"series": [
"Температура, С",
"Влажность, %"
],
"dateFormat": "HH:mm",
"maxCount": 86400,
"pointRadius": 0
},
{
"name": "chart6",
"label": "График тройной",
"widget": "chart",
"series": [
"Температура, С",
"Влажность, %",
"Давление, кПа"
],
"dateFormat": "HH:mm",
"maxCount": 86400,
"pointRadius": 0
},
{
"name": "fillgauge",
"label": "Бочка",
"widget": "fillgauge",
"circleColor": "#00FFFF",
"textColor": "#FFFFFF",
"waveTextColor": "#000000",
"waveColor": "#00FFFF"
},
{
"name": "inputDate",
"label": "Ввод даты",
"widget": "input",
"size": "small",
"color": "orange",
"type": "date"
},
{
"name": "inputDgt",
"label": "Ввод числа",
"widget": "input",
"color": "blue",
"type": "number"
},
{
"name": "inputTxt",
"label": "Ввод текста",
"widget": "input",
"size": "small",
"color": "orange",
"type": "text"
},
{
"name": "inputTm",
"label": "Ввод времени",
"widget": "input",
"color": "blue",
"type": "time"
},
{
"name": "progressLine",
"label": "Статус линия",
"widget": "progress-line",
"icon": "sunny",
"max": "100",
"stroke": "10"
},
{
"name": "progressRound",
"label": "Статус круг",
"widget": "progress-round",
"max": "100",
"stroke": "20",
"color": "#45ccce",
"background": "#777",
"semicircle": "1"
},
{
"name": "range",
"label": "Ползунок",
"widget": "range",
"descrColor": "red",
"after": "%",
"k": 0.0977,
"min": 0,
"max": 100,
"debounce": 500
},
{
"name": "rangeServo",
"label": "Ползунок (Servo)",
"widget": "range",
"descrColor": "red",
"after": "°",
"k": 1,
"min": 0,
"max": 180,
"debounce": 500
},
{
"name": "select",
"label": "Выпадающий",
"widget": "select",
"options": [
"Выключен",
"Включен"
],
"status": 0
},
{
"name": "anydataPpm",
"label": "PPM",
"widget": "anydata",
"after": "ppm",
"icon": "speedometer"
},
{
"name": "anydatamAmp",
"label": "миллиАмперы",
"widget": "anydata",
"after": "mAmp",
"icon": "speedometer"
},
{
"name": "anydatamVlt",
"label": "миллиВольты",
"widget": "anydata",
"after": "mVlt",
"icon": "speedometer"
},
{
"name": "anydatamWt",
"label": "миллиВатты",
"widget": "anydata",
"after": "mWt",
"icon": "speedometer"
},
{
"name": "anydataKm",
"label": "Километры",
"widget": "anydata",
"after": "km",
"icon": "speedometer"
},
{
"name": "anydataM",
"label": "Метры",
"widget": "anydata",
"after": "m",
"icon": "speedometer"
},
{
"name": "anydataCm",
"label": "Сантиметры",
"widget": "anydata",
"after": "cm",
"icon": "speedometer"
},
{
"name": "anydataLiter",
"label": "Литры",
"widget": "anydata",
"after": "ltr",
"icon": "speedometer"
},
{
"name": "anydataSpeed",
"label": "мерты в секунду",
"widget": "anydata",
"after": "m/s",
"icon": "speedometer"
},
{
"name": "anydataСorner",
"label": "угол градусов",
"widget": "anydata",
"after": "°",
"icon": "speedometer"
},
{
"name": "anydataBar",
"label": "давление Bar",
"widget": "anydata",
"after": "Kg/cm²",
"icon": "speedometer"
},
{
"name": "nil",
"label": "Без виджета"
}
]