-
-
-
-
+
diff --git a/data/Control/openevse.json b/data/Control/openevse.json
new file mode 100644
index 0000000..2942cba
--- /dev/null
+++ b/data/Control/openevse.json
@@ -0,0 +1,41 @@
+{
+ "name": "OpenEVSE",
+ "category": "Control",
+ "group": "MQTT",
+ "description": "OpenEVSE control",
+ "inputs": [
+ {
+ "name": "period",
+ "description": "Control period",
+ "processList": []
+ },
+ {
+ "name": "end",
+ "description": "Control end",
+ "processList": []
+ },
+ {
+ "name": "interruptible",
+ "description": "Control interruptible",
+ "processList": []
+ },
+ {
+ "name": "status",
+ "description": "Control status",
+ "processList": []
+ }
+ ],
+
+ "feeds": [],
+
+ "control":
+ {
+ "active": {"name":"Active","type":"checkbox","default":1},
+ "period": {"name":"Run period", "type":"time","default":0,"resolution":0.5},
+ "end": {"name":"Complete by", "type":"time","default":0,"resolution":0.5},
+ "repeat": {"type":"weekly-scheduler","default":[1,1,1,1,1,0,0]},
+ "interruptible": {"name":"Ok to interrupt schedule","type":"checkbox","default":0},
+ "runonce": {"type":"","default":true},
+ "basic": {"type":"","default":0}
+ }
+}
diff --git a/data/Control/smartplug.json b/data/Control/smartplug.json
new file mode 100644
index 0000000..45411d4
--- /dev/null
+++ b/data/Control/smartplug.json
@@ -0,0 +1,41 @@
+{
+ "name": "Smartplug",
+ "category": "Control",
+ "group": "MQTT",
+ "description": "Smartplug control",
+ "inputs": [
+ {
+ "name": "period",
+ "description": "Control period",
+ "processList": []
+ },
+ {
+ "name": "end",
+ "description": "Control end",
+ "processList": []
+ },
+ {
+ "name": "interruptible",
+ "description": "Control interruptible",
+ "processList": []
+ },
+ {
+ "name": "status",
+ "description": "Control status",
+ "processList": []
+ }
+ ],
+
+ "feeds": [],
+
+ "control":
+ {
+ "active": {"name":"Active","type":"checkbox","default":1},
+ "period": {"name":"Run period", "type":"time","default":0,"resolution":0.5},
+ "end": {"name":"Complete by", "type":"time","default":0,"resolution":0.5},
+ "repeat": {"type":"weekly-scheduler","default":[1,1,1,1,1,0,0]},
+ "interruptible": {"name":"Ok to interrupt schedule","type":"checkbox","default":0},
+ "runonce": {"type":"","default":true},
+ "basic": {"type":"","default":0}
+ }
+}
diff --git a/data/Control/wifirelay.json b/data/Control/wifirelay.json
new file mode 100644
index 0000000..042972a
--- /dev/null
+++ b/data/Control/wifirelay.json
@@ -0,0 +1,41 @@
+{
+ "name": "Wi-Fi relay",
+ "category": "Control",
+ "group": "MQTT",
+ "description": "Wi-Fi relay control",
+ "inputs": [
+ {
+ "name": "period",
+ "description": "Control period",
+ "processList": []
+ },
+ {
+ "name": "end",
+ "description": "Control end",
+ "processList": []
+ },
+ {
+ "name": "interruptible",
+ "description": "Control interruptible",
+ "processList": []
+ },
+ {
+ "name": "status",
+ "description": "Control status",
+ "processList": []
+ }
+ ],
+
+ "feeds": [],
+
+ "control":
+ {
+ "active": {"name":"Active","type":"checkbox","default":1},
+ "period": {"name":"Run period", "type":"time","default":0,"resolution":0.5},
+ "end": {"name":"Complete by", "type":"time","default":0,"resolution":0.5},
+ "repeat": {"type":"weekly-scheduler","default":[1,1,1,1,1,0,0]},
+ "interruptible": {"name":"Ok to interrupt schedule","type":"checkbox","default":0},
+ "runonce": {"type":"","default":true},
+ "basic": {"type":"","default":0}
+ }
+}
diff --git a/data/OpenEnergyMonitor/emonpi-HEM.json b/data/OpenEnergyMonitor/emonpi-HEM.json
new file mode 100644
index 0000000..fcda22b
--- /dev/null
+++ b/data/OpenEnergyMonitor/emonpi-HEM.json
@@ -0,0 +1,37 @@
+{
+ "name": "HomeEnergyMonitor",
+ "category": "OpenEnergyMonitor",
+ "group": "EmonPi",
+ "description": "Basic EmonPi Home Energy Monitor configuration",
+ "inputs": [
+ {
+ "name": "power1",
+ "description": "House consumption",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": { "type": "ProcessArg::FEEDID", "value": "use" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": { "type": "ProcessArg::FEEDID", "value": "use_kwh" }
+ }
+ ]
+ }
+ ],
+
+ "feeds": [
+ {
+ "name": "use",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "use_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ }
+ ]
+}
diff --git a/data/OpenEnergyMonitor/emonpi-SPV1.json b/data/OpenEnergyMonitor/emonpi-SPV1.json
new file mode 100644
index 0000000..243769e
--- /dev/null
+++ b/data/OpenEnergyMonitor/emonpi-SPV1.json
@@ -0,0 +1,91 @@
+{
+ "name": "Solar PV Type 1",
+ "category": "OpenEnergyMonitor",
+ "group": "EmonPi",
+ "description": "EmonPi Solar PV Type 1 template",
+ "inputs": [
+ {
+ "name": "power1",
+ "description": "House consumption",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use_kwh" }
+ },
+ {
+ "process": "subtract_input",
+ "arguments": {"type": "ProcessArg::INPUTID", "value": "power2" }
+ },
+ {
+ "process": "allowpositive",
+ "arguments": {"type": "ProcessArg::NONE"}
+ },
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "import" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "import_kwh" }
+ }
+ ]
+ },
+ {
+ "name": "power2",
+ "description": "Solar generation",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "solar" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "solar_kwh" }
+ }
+ ]
+ }
+ ],
+
+ "feeds": [
+ {
+ "name": "use",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "use_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "solar",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "solar_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "import",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "import_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ }
+ ]
+}
diff --git a/data/OpenEnergyMonitor/emonpi-SPV2.json b/data/OpenEnergyMonitor/emonpi-SPV2.json
new file mode 100644
index 0000000..3718e45
--- /dev/null
+++ b/data/OpenEnergyMonitor/emonpi-SPV2.json
@@ -0,0 +1,91 @@
+{
+ "name": "Solar PV Type 2",
+ "category": "OpenEnergyMonitor",
+ "group": "EmonPi",
+ "description": "EmonPi Solar PV Type 2 template",
+ "inputs": [
+ {
+ "name": "power1",
+ "description": "House consumption",
+ "processList": [
+ {
+ "process": "allowpositive",
+ "arguments": {"type": "ProcessArg::NONE"}
+ },
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "import" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "import_kwh" }
+ }
+ ]
+ },
+ {
+ "name": "power2",
+ "description": "Solar generation",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "solar" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "solar_kwh" }
+ },
+ {
+ "process": "add_input",
+ "arguments": {"type": "ProcessArg::INPUTID", "value": "power1" }
+ },
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use_kwh" }
+ }
+ ]
+ }
+ ],
+
+ "feeds": [
+ {
+ "name": "use",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "use_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "solar",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "solar_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "import",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "import_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ }
+ ]
+}
diff --git a/data/OpenEnergyMonitor/emonth.json b/data/OpenEnergyMonitor/emonth.json
new file mode 100644
index 0000000..9f03e4f
--- /dev/null
+++ b/data/OpenEnergyMonitor/emonth.json
@@ -0,0 +1,43 @@
+{
+ "name": "EmonTH",
+ "category": "OpenEnergyMonitor",
+ "group": "Temperature & Humidity",
+ "description": "Automatic inputs and feeds creation for emonTH device.",
+ "inputs": [
+ {
+ "name": "temperature",
+ "description": "Temperature C",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "emonth_temperature" }
+ }
+ ]
+ },
+ {
+ "name": "humidity",
+ "description": "Humidity Rh%",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "emonth_humidity" }
+ }
+ ]
+ }
+ ],
+
+ "feeds": [
+ {
+ "name": "emonth_temperature",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "60"
+ },
+ {
+ "name": "emonth_humidity",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "60"
+ }
+ ]
+}
diff --git a/data/OpenEnergyMonitor/emontx-HEM.json b/data/OpenEnergyMonitor/emontx-HEM.json
new file mode 100644
index 0000000..bb638af
--- /dev/null
+++ b/data/OpenEnergyMonitor/emontx-HEM.json
@@ -0,0 +1,37 @@
+{
+ "name": "HomeEnergyMonitor",
+ "category": "OpenEnergyMonitor",
+ "group": "EmonTx",
+ "description": "Basic EmonTx v3 Home Energy Monitor configuration",
+ "inputs": [
+ {
+ "name": "power1",
+ "description": "House consumption",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use_kwh" }
+ }
+ ]
+ }
+ ],
+
+ "feeds": [
+ {
+ "name": "use",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "use_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ }
+ ]
+}
diff --git a/data/OpenEnergyMonitor/emontx-HP.json b/data/OpenEnergyMonitor/emontx-HP.json
new file mode 100644
index 0000000..0e3328c
--- /dev/null
+++ b/data/OpenEnergyMonitor/emontx-HP.json
@@ -0,0 +1,37 @@
+{
+ "name": "Heatpump Monitor",
+ "category": "OpenEnergyMonitor",
+ "group": "EmonTx",
+ "description": "Heatpump Monitor firmware for EmonTx v3",
+ "inputs": [
+ {
+ "name": "P1",
+ "description": "Consumption",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use_kwh" }
+ }
+ ]
+ }
+ ],
+
+ "feeds": [
+ {
+ "name": "use",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "use_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ }
+ ]
+}
diff --git a/data/OpenEnergyMonitor/emontx-SPV1.json b/data/OpenEnergyMonitor/emontx-SPV1.json
new file mode 100644
index 0000000..d0ff3fe
--- /dev/null
+++ b/data/OpenEnergyMonitor/emontx-SPV1.json
@@ -0,0 +1,91 @@
+{
+ "name": "Solar PV Type 1",
+ "category": "OpenEnergyMonitor",
+ "group": "EmonTx",
+ "description": "EmonTx Solar PV Type 1 template using CT4 for solar",
+ "inputs": [
+ {
+ "name": "power1",
+ "description": "House consumption",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use_kwh" }
+ },
+ {
+ "process": "subtract_input",
+ "arguments": {"type": "ProcessArg::INPUTID", "value": "power4" }
+ },
+ {
+ "process": "allowpositive",
+ "arguments": {"type": "ProcessArg::NONE"}
+ },
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "import" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "import_kwh" }
+ }
+ ]
+ },
+ {
+ "name": "power4",
+ "description": "Solar generation",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "solar" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "solar_kwh" }
+ }
+ ]
+ }
+ ],
+
+ "feeds": [
+ {
+ "name": "use",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "use_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "solar",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "solar_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "import",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "import_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ }
+ ]
+}
diff --git a/data/OpenEnergyMonitor/emontx-SPV2.json b/data/OpenEnergyMonitor/emontx-SPV2.json
new file mode 100644
index 0000000..fe604ce
--- /dev/null
+++ b/data/OpenEnergyMonitor/emontx-SPV2.json
@@ -0,0 +1,91 @@
+{
+ "name": "Solar PV Type 2",
+ "category": "OpenEnergyMonitor",
+ "group": "EmonTx",
+ "description": "EmonTx Solar PV Type 2 template using CT4 for solar",
+ "inputs": [
+ {
+ "name": "power1",
+ "description": "House consumption",
+ "processList": [
+ {
+ "process": "allowpositive",
+ "arguments": {"type": "ProcessArg::NONE"}
+ },
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "import" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "import_kwh" }
+ }
+ ]
+ },
+ {
+ "name": "power4",
+ "description": "Solar generation",
+ "processList": [
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "solar" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "solar_kwh" }
+ },
+ {
+ "process": "add_input",
+ "arguments": {"type": "ProcessArg::INPUTID", "value": "power1" }
+ },
+ {
+ "process": "log_to_feed",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use" }
+ },
+ {
+ "process": "power_to_kwh",
+ "arguments": {"type": "ProcessArg::FEEDID", "value": "use_kwh" }
+ }
+ ]
+ }
+ ],
+
+ "feeds": [
+ {
+ "name": "use",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "use_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "solar",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "solar_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "import",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ },
+ {
+ "name": "import_kwh",
+ "type": "DataType::REALTIME",
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
+ }
+ ]
+}
diff --git a/data/amig.json b/data/amig.json
index d94674d..a75daf4 100644
--- a/data/amig.json
+++ b/data/amig.json
@@ -1,11 +1,13 @@
{
"name": "AMIG",
+ "category": "Datalogger",
+ "group": "ArchiMetrics",
"description": "INPUTS & FEEDS for AMIG Logger from archimetrics.co.uk",
"inputs": [{
"name": "n1T",
"description": "N1 Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n1T"
@@ -16,7 +18,7 @@
"name": "n1R",
"description": "N1 RH",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n1R"
@@ -27,7 +29,7 @@
"name": "n1D",
"description": "N1 DewPoint",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n1D"
@@ -38,7 +40,7 @@
"name": "n2T",
"description": "N2 Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n2T"
@@ -49,7 +51,7 @@
"name": "n2R",
"description": "N2 RH",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n2R"
@@ -60,7 +62,7 @@
"name": "n2D",
"description": "N2 DewPoint",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n2D"
@@ -71,7 +73,7 @@
"name": "n3T",
"description": "N3 Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n3T"
@@ -82,7 +84,7 @@
"name": "n3R",
"description": "N3 RH",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n3R"
@@ -93,7 +95,7 @@
"name": "n3D",
"description": "N3 DewPoint",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n3D"
@@ -104,7 +106,7 @@
"name": "n4T",
"description": "N4 Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n4T"
@@ -115,7 +117,7 @@
"name": "n4R",
"description": "N4 RH",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n4R"
@@ -126,7 +128,7 @@
"name": "n4D",
"description": "N4 DewPoint",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n4D"
@@ -137,7 +139,7 @@
"name": "iTS",
"description": "Internal Temperature Surface",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "iTS"
@@ -148,7 +150,7 @@
"name": "eTS",
"description": "External Temperature Surface",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "eTS"
@@ -159,7 +161,7 @@
"name": "eSR",
"description": "External Solar Radiation",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "eSR"
@@ -170,7 +172,7 @@
"name": "iTA",
"description": "Internal Temperature Air",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "iTA"
@@ -181,7 +183,7 @@
"name": "iRH",
"description": "Internal RH",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "iRH"
@@ -192,7 +194,7 @@
"name": "iDP",
"description": "Internal DewPoint",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "iDP"
@@ -203,7 +205,7 @@
"name": "eTA",
"description": "External Temperature Air",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "eTA"
@@ -214,7 +216,7 @@
"name": "eRH",
"description": "External RH",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "eRH"
@@ -225,7 +227,7 @@
"name": "eDP",
"description": "External DewPoint",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "eDP"
@@ -236,7 +238,7 @@
"name": "hfV",
"description": "HeatFlux Voltage",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "hfV"
@@ -247,7 +249,7 @@
"name": "hfW",
"description": "HeatFlux Watts",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "hfW"
@@ -258,7 +260,7 @@
"name": "CO2",
"description": "Carbon Dioxide",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "CO2"
@@ -269,7 +271,7 @@
"name": "SYS",
"description": "System Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "SYS"
@@ -279,151 +281,151 @@
"feeds": [{
"name": "n1T",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n1R",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n1D",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n2T",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n2R",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n2D",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n3T",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n3R",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n3D",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n4T",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n4R",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "n4D",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "iTS",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "eTS",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "eSR",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "iTA",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "iRH",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "iDP",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "eTA",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "eRH",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "eDP",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "hfV",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "hfW",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "CO2",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
},
{
"name": "SYS",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
+ "engine": "Engine::PHPFINA",
+ "interval": "10"
}]
-}
\ No newline at end of file
+}
diff --git a/data/amrm.json b/data/amrm.json
index 8c7f021..e9e2873 100644
--- a/data/amrm.json
+++ b/data/amrm.json
@@ -1,11 +1,13 @@
{
"name": "AMRM",
+ "category": "Datalogger",
+ "group": "ArchiMetrics",
"description": "INPUTS & FEEDS for AMRM Logger from archimetrics.co.uk",
"inputs": [{
"name": "n1T",
"description": "N1 Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n1T"
@@ -16,7 +18,7 @@
"name": "n2T",
"description": "N2 Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n2T"
@@ -27,7 +29,7 @@
"name": "n3T",
"description": "N3 Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n3T"
@@ -38,7 +40,7 @@
"name": "n4T",
"description": "N4 Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n4T"
@@ -49,7 +51,7 @@
"name": "n1IM",
"description": "N1 IM",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n1IM"
@@ -60,7 +62,7 @@
"name": "n2IM",
"description": "N2 IM",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n2IM"
@@ -71,7 +73,7 @@
"name": "n3IM",
"description": "N3 IM",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n3IM"
@@ -82,7 +84,7 @@
"name": "n4IM",
"description": "N4 IM",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n4IM"
@@ -93,7 +95,7 @@
"name": "n1DM",
"description": "N1 DM",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n1DM"
@@ -104,7 +106,7 @@
"name": "n2DM",
"description": "N2 DM",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n2DM"
@@ -115,7 +117,7 @@
"name": "n3DM",
"description": "N3 DM",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n3DM"
@@ -126,7 +128,7 @@
"name": "n4DM",
"description": "N4 DM",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "n4DM"
@@ -137,7 +139,7 @@
"name": "iTA",
"description": "Internal Temperature Air",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "iTA"
@@ -148,7 +150,7 @@
"name": "iRH",
"description": "Internal RH",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "iRH"
@@ -159,7 +161,7 @@
"name": "iDP",
"description": "Internal Dew Point",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "iDP"
@@ -170,7 +172,7 @@
"name": "SYS",
"description": "System Temperature",
"processList": [{
- "process": "1",
+ "process": "log_to_feed",
"arguments": {
"type": "ProcessArg::FEEDID",
"value": "SYS"
@@ -180,98 +182,98 @@
"feeds": [{
"name": "n1T",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n2T",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n3T",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n4T",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n1IM",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n2IM",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n3IM",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n4IM",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n1DM",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n2DM",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n3DM",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "n4DM",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "iTA",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "iRH",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "iDP",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
},
{
"name": "SYS",
"type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
+ "engine": "Engine::PHPFINA",
"interval": "10"
}]
}
diff --git a/data/emonth.json b/data/emonth.json
deleted file mode 100644
index 41e9aac..0000000
--- a/data/emonth.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{ "name": "EmonTH",
- "description": "Automatic inputs and feeds creation for emonTH device.",
- "inputs": [
- {
- "name": "1",
- "description": "Temperature C",
- "processList": [
- {
- "process": "1",
- "arguments": {"type": "ProcessArg::FEEDID", "value": "tempC" }
- }
- ]
- },
- {
- "name": "2",
- "description": "Humidity Rh%",
- "processList": [
- {
- "process": "1",
- "arguments": {"type": "ProcessArg::FEEDID", "value": "humiRH" }
- }
- ]
- },
- {
- "name": "3",
- "description": "Internal Battery",
- "processList": [
- {
- "process": "1",
- "arguments": {"type": "ProcessArg::FEEDID", "value": "batV" }
- }
- ]
- }
- ],
-
- "feeds": [
- {
- "name": "tempC",
- "type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
- },
- {
- "name": "humiRH",
- "type": "DataType::REALTIME",
- "engine": "Engine::MYSQL"
- },
- {
- "name": "batV",
- "type": "DataType::REALTIME",
- "engine": "Engine::MYSQL"
- }
- ]
-}
\ No newline at end of file
diff --git a/data/example.json b/data/example.json
deleted file mode 100644
index 4816fce..0000000
--- a/data/example.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{ "name": "Demonstration",
- "description": "Automatic inputs and feeds creation for demonstration devices.",
- "inputs": [
- {
- "name": "iload",
- "description": "Consumption intensity",
- "processList": [
- {
- "process": "1",
- "arguments": {"type": "ProcessArg::FEEDID", "value": "fILoad" }
- },
- {
- "process": "29",
- "arguments": {"type": "ProcessArg::FEEDID", "value": "fPLoad" }
- }
- ]
- },
- {
- "name": "pload",
- "description": "Consumption power",
- "processList": ""
- }
- ],
-
- "feeds": [
- {
- "name": "fILoad",
- "type": "DataType::REALTIME",
- "engine": "Engine::MYSQL",
- "interval": "5"
- },
- {
- "name": "fPLoad",
- "type": "DataType::REALTIME",
- "engine": "Engine::MYSQL"
- },
- {
- "name": "fVirtual",
- "type": "DataType::REALTIME",
- "engine": "Engine::VIRTUALFEED",
- "processList": [
- {
- "process": "53",
- "arguments": {"type": "ProcessArg::FEEDID", "value": "fILoad" }
- },
- {
- "process": "2",
- "arguments": {"type": "ProcessArg::VALUE", "value": "2" }
- }
- ]
- }
- ]
-}
\ No newline at end of file
diff --git a/data/smartmeter.json b/data/smartmeter.json
deleted file mode 100644
index 8707a86..0000000
--- a/data/smartmeter.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "name": "smartmeter",
- "description": "Automatic inputs and feeds creation for smartmeter device.",
- "inputs": [
- {
- "name": "P1",
- "description": "CT1 Power",
- "processList": [
- {
- "process": "1",
- "arguments": {"type": "ProcessArg::FEEDID", "value": "use" }
- },
- {
- "process": "4",
- "arguments": {"type": "ProcessArg::FEEDID", "value": "use_kwh" }
- }
- ]
- },
- {
- "name": "E1",
- "description": "CT1 Energy",
- "processList": [
- {
- "process": "34",
- "arguments": {"type": "ProcessArg::FEEDID", "value": "use_wh" }
- }
- ]
- }
- ],
-
- "feeds": [
- {
- "name": "use",
- "type": "DataType::REALTIME",
- "engine": "Engine::PHPFINA",
- "interval": "10"
- },
- {
- "name": "use_kwh",
- "type": "DataType::REALTIME",
- "engine": "Engine::PHPFINA",
- "interval": "10"
- },
- {
- "name": "use_wh",
- "type": "DataType::REALTIME",
- "engine": "Engine::PHPFINA",
- "interval": "10"
- }
- ]
-}
diff --git a/device_controller.php b/device_controller.php
index b000c69..9f571fd 100644
--- a/device_controller.php
+++ b/device_controller.php
@@ -5,7 +5,7 @@
function device_controller()
{
- global $session,$route,$mysqli,$user,$redis;
+ global $mysqli, $redis, $session, $route, $device;
$result = false;
@@ -15,26 +15,64 @@ function device_controller()
if ($route->format == 'html')
{
if ($route->action == "view" && $session['write']) {
- $devices_templates = $device->get_templates();
- $result = view("Modules/device/Views/device_view.php",array('devices_templates'=>$devices_templates));
+ $templates = $device->get_template_list_meta($session['userid']);
+ $result = view("Modules/device/Views/device_view.php", array('templates'=>$templates));
}
- if ($route->action == 'api') $result = view("Modules/device/Views/device_api.php", array());
+ else if ($route->action == 'api') $result = view("Modules/device/Views/device_api.php", array());
}
if ($route->format == 'json')
{
- // Used in conjunction with input name describe to auto create device
- if ($route->action == "autocreate") {
- if ($session['userid']>0 && $session['write']) $result = $device->autocreate($session['userid'],get('nodeid'),get('type'));
+ // ---------------------------------------------------------------
+ // Method for sharing authentication details with a node
+ // that does not require copying and pasting passwords and apikeys
+ // 1. device requests authentication - reply "request registered"
+ // 2. notification asks user whether to allow or deny device
+ // 3. user clicks on allow
+ // 4. device makes follow up request for authentication
+ // - reply authentication details
+ // ---------------------------------------------------------------
+ if ($route->action == "auth") {
+ if ($route->subaction=="request") {
+ // 1. Register request for authentication details, or provide if allowed
+ $result = $device->request_auth($_SERVER['REMOTE_ADDR']);
+ if (isset($result["success"])) {
+ $result = $result["message"];
+ }
+ $route->format = "text";
+ }
+ else if ($route->subaction=="check" && $session['write']) {
+ // 2. User checks for device waiting for authentication
+ $result = $device->get_auth_request();
+ }
+ else if ($route->subaction=="allow" && $session['write']) {
+ // 3. User allows device to receive authentication details
+ $result = $device->allow_auth_request(get("ip"));
+ }
}
else if ($route->action == 'list') {
if ($session['userid']>0 && $session['write']) $result = $device->get_list($session['userid']);
}
- elseif ($route->action == "create") {
- if ($session['userid']>0 && $session['write']) $result = $device->create($session['userid']);
+ else if ($route->action == "create") {
+ if ($session['userid']>0 && $session['write']) $result = $device->create($session['userid'],get("nodeid"),get("name"),get("description"),get("type"),get("options"));
}
- elseif ($route->action == "listtemplates") {
- if ($session['userid']>0 && $session['write']) $result = $device->get_templates();
+ // Used in conjunction with input name describe to auto create device
+ else if ($route->action == "autocreate") {
+ if ($session['userid']>0 && $session['write']) $result = $device->autocreate($session['userid'],get('nodeid'),get('type'));
+ }
+ else if ($route->action == "template" && $route->subaction != "prepare" && $route->subaction != "init") {
+ if ($route->subaction == "listshort") {
+ if ($session['userid']>0 && $session['write']) $result = $device->get_template_list_meta($session['userid']);
+ }
+ else if ($route->subaction == "list") {
+ if ($session['userid']>0 && $session['write']) $result = $device->get_template_list($session['userid']);
+ }
+ else if ($route->subaction == "reload") {
+ if ($session['userid']>0 && $session['write']) $result = $device->reload_template_list($session['userid']);
+ }
+ else if ($route->subaction == "get") {
+ if ($session['userid']>0 && $session['write']) $result = $device->get_template($session['userid'], get('type'));
+ }
}
else {
$deviceid = (int) get('id');
@@ -43,16 +81,23 @@ function device_controller()
$deviceget = $device->get($deviceid);
if (isset($session['write']) && $session['write'] && $session['userid']>0 && $deviceget['userid']==$session['userid']) {
if ($route->action == "get") $result = $deviceget;
- if ($route->action == "delete") $result = $device->delete($deviceid);
- if ($route->action == 'set') $result = $device->set_fields($deviceid, get('fields'));
- if ($route->action == 'inittemplate') $result = $device->init_template($deviceid);
+ else if ($route->action == 'set') $result = $device->set_fields($deviceid, get('fields'));
+ else if ($route->action == 'init') $result = $device->init($deviceid, prop('template'));
+ else if ($route->action == "delete") $result = $device->delete($deviceid);
+ else if ($route->action == "setnewdevicekey") $result = $device->set_new_devicekey($deviceid);
+ else if ($route->action == 'template') {
+ if (isset($_GET['type'])) {
+ $device->set_fields($deviceid, json_encode(array("type"=>$_GET['type'])));
+ }
+ if ($route->subaction == 'prepare') $result = $device->prepare_template($deviceid);
+ else if ($route->subaction == 'init') $result = $device->init_template($deviceget, $_POST['template']);
+ }
}
}
- else
- {
+ else {
$result = array('success'=>false, 'message'=>'Device does not exist');
}
- }
+ }
}
return array('content'=>$result);
diff --git a/device_menu.php b/device_menu.php
index def92bb..480ea6c 100644
--- a/device_menu.php
+++ b/device_menu.php
@@ -4,4 +4,10 @@
bindtextdomain($domain, "Modules/device/locale");
bind_textdomain_codeset($domain, 'UTF-8');
- $menu_dropdown_config[] = array('name'=> dgettext($domain, "Device Setup"), 'icon'=>'icon-facetime-video', 'path'=>"device/view" , 'session'=>"write", 'order' => 45 );
+ $menu_dropdown_config[] = array(
+ 'name'=> dgettext($domain, "Device Setup"),
+ 'icon'=>'icon-home',
+ 'path'=>"device/view" ,
+ 'session'=>"write",
+ 'order' => 45
+ );
diff --git a/device_model.php b/device_model.php
index d9941da..f178ec3 100644
--- a/device_model.php
+++ b/device_model.php
@@ -1,532 +1,688 @@
mysqli = $mysqli;
$this->redis = $redis;
+ $this->templates = array();
$this->log = new EmonLogger(__FILE__);
}
- public function devicekey_session($devicekey_in)
- {
- $devicekey_in = $this->mysqli->real_escape_string($devicekey_in);
+ public function devicekey_session($devicekey) {
+ // 1. Only allow alphanumeric characters
+ // if (!ctype_alnum($devicekey)) return array();
+
+ // 2. Only allow 32 character length
+ if (strlen($devicekey)!=32) return array();
+
$session = array();
$time = time();
-
+
//----------------------------------------------------
// Check for devicekey login
//----------------------------------------------------
- if($this->redis && $this->redis->exists("device:key:$devicekey_in"))
- {
- $session['userid'] = $this->redis->get("device:key:$devicekey_in:user");
+ if($this->redis && $this->redis->exists("device:key:$devicekey")) {
+ $session['userid'] = $this->redis->get("device:key:$devicekey:user");
$session['read'] = 0;
$session['write'] = 1;
$session['admin'] = 0;
$session['lang'] = "en"; // API access is always in english
$session['username'] = "API";
- $session['deviceid'] = $this->redis->get("device:key:$devicekey_in:device");
- $session['nodeid'] = $this->redis->get("device:key:$devicekey_in:node");
+ $session['deviceid'] = $this->redis->get("device:key:$devicekey:device");
+ $session['nodeid'] = $this->redis->get("device:key:$devicekey:node");
$this->redis->hMset("device:lastvalue:".$session['device'], array('time' => $time));
}
- else
- {
- $result = $this->mysqli->query("SELECT id, userid, nodeid FROM device WHERE devicekey='$devicekey_in'");
- if ($result->num_rows == 1)
- {
- $row = $result->fetch_array();
- if ($row['id'] != 0)
- {
- $session['userid'] = $row['userid'];
- $session['read'] = 0;
- $session['write'] = 1;
- $session['admin'] = 0;
- $session['lang'] = "en"; // API access is always in english
- $session['username'] = "API";
- $session['deviceid'] = $row['id'];
- $session['nodeid'] = $row['nodeid'];
+ else {
+ $stmt = $this->mysqli->prepare("SELECT id, userid, nodeid FROM device WHERE devicekey=?");
+ $stmt->bind_param("s",$devicekey);
+ $stmt->execute();
+ $stmt->bind_result($id,$userid,$nodeid);
+ $result = $stmt->fetch();
+ $stmt->close();
+
+ if ($result && $id>0) {
+ $session['userid'] = $userid;
+ $session['read'] = 0;
+ $session['write'] = 1;
+ $session['admin'] = 0;
+ $session['lang'] = "en"; // API access is always in english
+ $session['username'] = "API";
+ $session['deviceid'] = $id;
+ $session['nodeid'] = $nodeid;
- if ($this->redis) {
- $this->redis->set("device:key:$devicekey_in:user",$row['userid']);
- $this->redis->set("device:key:$devicekey_in:device",$row['id']);
- $this->redis->set("device:key:$devicekey_in:node",$row['nodeid']);
- $this->redis->hMset("device:lastvalue:".$row['id'], array('time' => $time));
- } else {
- //$time = date("Y-n-j H:i:s", $time);
- $this->mysqli->query("UPDATE device SET time='$time' WHERE id = '".$row['id']."'");
- }
+ if ($this->redis) {
+ $this->redis->set("device:key:$devicekey:user",$userid);
+ $this->redis->set("device:key:$devicekey:device",$id);
+ $this->redis->set("device:key:$devicekey:node",$nodeid);
+ $this->redis->hMset("device:lastvalue:$id", array('time' => $time));
+ } else {
+ //$time = date("Y-n-j H:i:s", $time);
+ $this->mysqli->query("UPDATE device SET time='$time' WHERE id = '$id");
}
}
}
-
+
return $session;
}
- public function exist($id)
- {
- $id = intval($id);
+ public function exist($id) {
static $device_exists_cache = array(); // Array to hold the cache
if (isset($device_exists_cache[$id])) {
- $deviceexist = $device_exists_cache[$id]; // Retrieve from static cache
- } else {
- $result = $this->mysqli->query("SELECT id FROM device WHERE id = '$id'");
- $deviceexist = $result->num_rows>0;
- $device_exists_cache[$id] = $deviceexist; // Cache it
- $this->log->info("exist() $id");
+ $device_exist = $device_exists_cache[$id]; // Retrieve from static cache
}
- return $deviceexist;
+ else {
+ $device_exist = false;
+ if ($this->redis) {
+ if (!$this->redis->exists("device:$id")) {
+ if ($this->load_device_to_redis($id)) {
+ $device_exist = true;
+ }
+ }
+ else {
+ $device_exist = true;
+ }
+ }
+ else {
+ $id = (int) $id;
+ $result = $this->mysqli->query("SELECT id FROM device WHERE id = '$id'");
+ if ($result->num_rows > 0) $device_exist = true;
+ }
+ $device_exists_cache[$id] = $device_exist; // Cache it
+ }
+ return $device_exist;
}
-
-
- public function exists_name($userid,$name)
- {
+
+ public function exists_name($userid, $name) {
$userid = intval($userid);
$name = preg_replace('/[^\p{L}_\p{N}\s-:]/u','',$name);
- $result = $this->mysqli->query("SELECT id FROM device WHERE userid = '$userid' AND name = '$name'");
- if ($result->num_rows>0) { $row = $result->fetch_array(); return $row['id']; } else return false;
+
+ $stmt = $this->mysqli->prepare("SELECT id FROM device WHERE userid=? AND name=?");
+ $stmt->bind_param("is", $userid, $name);
+ $stmt->execute();
+ $stmt->bind_result($id);
+ $result = $stmt->fetch();
+ $stmt->close();
+
+ if ($result && $id > 0) return $id; else return false;
}
- public function get($id)
- {
- $id = (int) $id;
- if (!$this->exist($id)) return array('success'=>false, 'message'=>'Device does not exist');
+ public function exists_nodeid($userid, $nodeid) {
+ $userid = intval($userid);
+ $nodeid = preg_replace('/[^\p{L}_\p{N}\s-:]/u','',$nodeid);
+
+ $stmt = $this->mysqli->prepare("SELECT id FROM device WHERE userid=? AND nodeid=?");
+ $stmt->bind_param("is", $userid, $nodeid);
+ $stmt->execute();
+ $stmt->bind_result($id);
+ $result = $stmt->fetch();
+ $stmt->close();
+
+ if ($result && $id > 0) return $id; else return false;
+ }
- $result = $this->mysqli->query("SELECT * FROM device WHERE id = '$id'");
- $row = (array) $result->fetch_object();
+ public function request_auth($ip) {
+ if (!$this->redis) {
+ return array("success"=>false, "message"=>"Unable to handle authentication requests without redis");
+ }
+ $ip_parts = explode(".", $ip);
+ for ($i=0; $i
redis->get("device:auth:allow");
+ // Only show authentication details to allowed ip address
+ if ($allow_ip == $ip) {
+ $this->redis->del("device:auth:allow");
+ global $mqtt_server;
+ return $mqtt_server["user"].":".$mqtt_server["password"].":".$mqtt_server["basetopic"];
+ } else {
+ $this->redis->set("device:auth:request", json_encode(array("ip"=>$ip)));
+ return array("success"=>true, "message"=>"Authentication request registered for IP $ip");
+ }
+ }
- return $row;
+ public function get_auth_request() {
+ if (!$this->redis) {
+ return array("success"=>false, "message"=>"Unable to handle authentication requests without redis");
+ }
+ if ($device_auth = $this->redis->get("device:auth:request")) {
+ $device_auth = json_decode($device_auth);
+ return array_merge(array("success"=>true, "ip"=>$device_auth->ip));
+ } else {
+ return array("success"=>true, "message"=>"No authentication request registered");
+ }
}
-
- public function get_list($userid)
- {
+
+ public function allow_auth_request($ip) {
+ if (!$this->redis) {
+ return array("success"=>false, "message"=>"Unable to handle authentication requests without redis");
+ }
+ $ip_parts = explode(".", $ip);
+ for ($i=0; $iredis->set("device:auth:allow", $ip); // Temporary availability of auth for device ip address
+ $this->redis->expire("device:auth:allow", 60); // Expire after 60 seconds
+ $this->redis->del("device:auth:request");
+
+ return array("success"=>true, "message"=>"Authentication request allowed for IP $ip");
+ }
+
+ public function get($id) {
+ $id = intval($id);
+ if (!$this->exist($id)) {
+ if (!$this->redis || !$this->load_device_to_redis($id)) {
+ return array('success'=>false, 'message'=>'Device does not exist');
+ }
+ }
+
if ($this->redis) {
- return $this->redis_getlist($userid);
+ // Get from redis cache
+ $device = (array) $this->redis->hGetAll("device:$id");
+ // Verify, if the cached device contains the userid, to avoid compatibility issues
+ // with former versions where the userid was not cached.
+ if (!isset($device['userid'])) {
+ $this->load_device_to_redis($id);
+ $device = $this->get($id);
+ }
+ $device['time'] = $this->redis->hget("device:lastvalue:".$id, 'time');
+ }
+ else {
+ // Get from mysql db
+ $result = $this->mysqli->query("SELECT `id`,`userid`,`nodeid`,`name`,`description`,`type`,`devicekey`,`time` FROM device WHERE id = '$id'");
+ $device = (array) $result->fetch_object();
+ }
+ return $device;
+ }
+
+ public function get_list($userid) {
+ if ($this->redis) {
+ return $this->get_list_redis($userid);
} else {
- return $this->mysql_getlist($userid);
+ return $this->get_list_mysql($userid);
}
}
- private function redis_getlist($userid)
- {
- $userid = (int) $userid;
- if (!$this->redis->exists("user:device:$userid")) $this->load_to_redis($userid);
+ private function get_list_redis($userid) {
+ $userid = intval($userid);
+
+ if (!$this->redis->exists("user:device:$userid")) {
+ $this->log->info("Load devices to redis in get_list_redis");
+ $this->load_list_to_redis($userid);
+ }
$devices = array();
$deviceids = $this->redis->sMembers("user:device:$userid");
- foreach ($deviceids as $id)
- {
- $row = $this->redis->hGetAll("device:$id");
- $lastvalue = $this->redis->hMget("device:lastvalue:".$id,array('time'));
- $row['time'] = $lastvalue['time'];
- $devices[] = $row;
+ foreach ($deviceids as $id) {
+ $device = $this->redis->hGetAll("device:$id");
+ // Verify, if the cached device contains the userid, to avoid compatibility issues
+ // with former versions where the userid was not cached.
+ if (!isset($device['userid'])) {
+ $this->load_device_to_redis($id);
+ $device = $this->get($id);
+ }
+ $device['time'] = $this->redis->hget("device:lastvalue:".$id, 'time');
+ $devices[] = $device;
}
+ usort($devices, function($d1, $d2) {
+ if($d1['nodeid'] == $d2['nodeid'])
+ return strcmp($d1['name'], $d2['name']);
+ return strcmp($d1['nodeid'], $d2['nodeid']);
+ });
return $devices;
}
- private function mysql_getlist($userid)
- {
- $userid = (int) $userid;
+ private function get_list_mysql($userid) {
+ $userid = intval($userid);
+
$devices = array();
-
- $result = $this->mysqli->query("SELECT `id`, `userid`, `name`, `description`, `type`, `nodeid`, `devicekey`, `time` FROM device WHERE userid = '$userid'");
- while ($row = (array)$result->fetch_object())
- {
- $devices[] = $row;
+ $result = $this->mysqli->query("SELECT `id`,`userid`,`nodeid`,`name`,`description`,`type`,`devicekey`,`time` FROM device WHERE userid = '$userid' ORDER BY nodeid, name asc");
+ while ($device = (array) $result->fetch_object()) {
+ $devices[] = $device;
}
return $devices;
}
- private function load_to_redis($userid)
- {
- $this->redis->delete("user:device:$userid");
- $result = $this->mysqli->query("SELECT `id`, `name`, `description`, `type`, `nodeid`, `devicekey` FROM device WHERE userid = '$userid'");
- while ($row = $result->fetch_object())
- {
+ private function load_list_to_redis($userid) {
+ $userid = intval($userid);
+
+ $result = $this->mysqli->query("SELECT `id`,`userid`,`nodeid`,`name`,`description`,`type`,`devicekey` FROM device WHERE userid = '$userid'");
+ while ($row = $result->fetch_object()) {
$this->redis->sAdd("user:device:$userid", $row->id);
- $this->redis->hMSet("device:".$row->id,array(
+ $this->redis->hMSet("device:".$row->id, array(
'id'=>$row->id,
+ 'userid'=>$row->userid,
+ 'nodeid'=>$row->nodeid,
'name'=>$row->name,
'description'=>$row->description,
'type'=>$row->type,
- 'nodeid'=>$row->nodeid,
'devicekey'=>$row->devicekey
));
}
}
-
- public function autocreate($userid,$_nodeid,$_type)
- {
+
+ private function load_device_to_redis($id) {
+ $id = intval($id);
+
+ $result = $this->mysqli->query("SELECT `id`,`userid`,`nodeid`,`name`,`description`,`type`,`devicekey` FROM device WHERE id = '$id'");
+ $row = $result->fetch_object();
+ if (!$row) {
+ $this->log->warn("Device model: Requested device does not exist for id=$id");
+ return false;
+ }
+ $this->redis->hMSet("device:".$row->id, array(
+ 'id'=>$row->id,
+ 'userid'=>$row->userid,
+ 'nodeid'=>$row->nodeid,
+ 'name'=>$row->name,
+ 'description'=>$row->description,
+ 'type'=>$row->type,
+ 'devicekey'=>$row->devicekey
+ ));
+ return true;
+ }
+
+ public function autocreate($userid, $_nodeid, $_type) {
$userid = intval($userid);
$nodeid = preg_replace('/[^\p{L}_\p{N}\s-:]/u','',$_nodeid);
- if ($_nodeid!=$nodeid) return array("success"=>false, "message"=>"Invalid nodeid");
+ if ($_nodeid != $nodeid) return array("success"=>false, "message"=>"Invalid nodeid");
$type = preg_replace('/[^\/\|\,\w\s-:]/','',$_type);
- if ($_type!=$type) return array("success"=>false, "message"=>"Invalid type");
+ if ($_type != $type) return array("success"=>false, "message"=>"Invalid type");
$name = "$nodeid:$type";
- if (!$this->exists_name($userid,$name)) {
- $deviceid = $this->create($userid);
- if ($deviceid>0) {
- $result = $this->set_fields($deviceid,json_encode(array("name"=>$name,"nodeid"=>$nodeid,"type"=>$type)));
- if ($result["success"]==true) {
- return $this->init_template($deviceid);
- } else {
- return $result;
- }
- } else {
- return array("success"=>false, "message"=>"Device creation failed");
- }
+ $deviceid = $this->exists_nodeid($userid, $nodeid);
+
+ if (!$deviceid) {
+ $this->log->info("Automatically create device for user=$userid, nodeid=$nodeid");
+ $deviceid = $this->create($userid, $nodeid, null, null, null);
+ if (!$deviceid) return array("success"=>false, "message"=>"Device creation failed");
+ }
+
+ $result = $this->set_fields($deviceid,json_encode(array("name"=>$name,"nodeid"=>$nodeid,"type"=>$type)));
+ if ($result["success"]==true) {
+ return $this->init_template($deviceid);
} else {
- return array("success"=>false, "message"=>"Device name already exists");
+ return $result;
}
- }
-
- public function create($userid)
- {
- $userid = intval($userid);
- $devicekey = md5(uniqid(mt_rand(), true));
- $this->mysqli->query("INSERT INTO device (`userid`, `name`, `description`, `nodeid`, `devicekey`) VALUES ('$userid','New Device','','New Node','$devicekey')");
- if ($this->redis) $this->load_to_redis($userid);
- return $this->mysqli->insert_id;
}
- public function delete($id)
- {
- $id = (int) $id;
- if (!$this->exist($id)) return array('success'=>false, 'message'=>'Device does not exist');
-
- if ($this->redis) {
- $result = $this->mysqli->query("SELECT userid FROM device WHERE `id` = '$id'");
- $row = (array) $result->fetch_object();
+ public function create($userid, $nodeid, $name, $description, $type) {
+ $userid = intval($userid);
+ $nodeid = preg_replace('/[^\p{L}_\p{N}\s-:]/u', '', $nodeid);
+
+ if (isset($name)) {
+ $name = preg_replace('/[^\p{L}_\p{N}\s-:]/u', '', $name);
+ } else {
+ $name = $nodeid;
+ }
+
+ if (isset($description)) {
+ $description = preg_replace('/[^\p{L}_\p{N}\s-:]/u', '', $description);
+ } else {
+ $description = '';
}
+
+ if (isset($type) && $type != 'null') {
+ $type = preg_replace('/[^\/\|\,\w\s-:]/','', $type);
+ } else {
+ $type = '';
+ }
+
+ if (!$this->exists_nodeid($userid, $nodeid)) {
+ $devicekey = md5(uniqid(mt_rand(), true));
+
+ $stmt = $this->mysqli->prepare("INSERT INTO device (userid,nodeid,name,description,type,devicekey) VALUES (?,?,?,?,?,?)");
+ $stmt->bind_param("isssss",$userid,$nodeid,$name,$description,$type,$devicekey);
+ $result = $stmt->execute();
+ $stmt->close();
+ if (!$result) return array('success'=>false, 'message'=>_("Error creating device"));
+
+ $deviceid = $this->mysqli->insert_id;
+
+ if ($deviceid > 0) {
+ // Add the device to redis
+ if ($this->redis) {
+ $this->redis->sAdd("user:device:$userid", $deviceid);
+ $this->redis->hMSet("device:".$deviceid, array(
+ 'id'=>$deviceid,
+ 'userid'=>$userid,
+ 'nodeid'=>$nodeid,
+ 'name'=>$name,
+ 'description'=>$description,
+ 'type'=>$type,
+ 'devicekey'=>$devicekey
+ ));
+ }
+ return $deviceid;
+ }
+ return array('success'=>false, 'result'=>"SQL returned invalid insert feed id");
+ }
+ return array('success'=>false, 'message'=>'Device already exists');
+ }
- $result = $this->mysqli->query("DELETE FROM device WHERE `id` = '$id'");
+ public function delete($id) {
+ $id = intval($id);
+ if (!$this->exist($id)) {
+ if (!$this->redis || !$this->load_device_to_redis($id)) {
+ return array('success'=>false, 'message'=>'Device does not exist');
+ }
+ }
+
+ $this->mysqli->query("DELETE FROM device WHERE `id` = '$id'");
if (isset($device_exists_cache[$id])) { unset($device_exists_cache[$id]); } // Clear static cache
if ($this->redis) {
- if (isset($row['userid']) && $row['userid']) {
- $this->redis->delete("device:".$id);
- $this->load_to_redis($row['userid']);
+ $userid = $this->redis->hget("device:$id",'userid');
+ if (isset($userid)) {
+ $this->redis->srem("user:device:$userid", $id);
+ $this->redis->del("device:$id");
}
}
}
- public function set_fields($id,$fields)
- {
- $id = (int) $id;
- if (!$this->exist($id)) return array('success'=>false, 'message'=>'Device does not exist');
-
+ public function set_fields($id, $fields) {
+ $id = intval($id);
+ if (!$this->exist($id)) {
+ if (!$this->redis || !$this->load_device_to_redis($id)) {
+ return array('success'=>false, 'message'=>'Device does not exist');
+ }
+ }
+ $success = true;
+
$fields = json_decode(stripslashes($fields));
- $array = array();
+ if (isset($fields->name)) {
+ if (preg_replace('/[^\p{N}\p{L}_\s-:]/u','',$fields->name)!=$fields->name) return array('success'=>false, 'message'=>'invalid characters in device name');
+ $stmt = $this->mysqli->prepare("UPDATE device SET name = ? WHERE id = ?");
+ $stmt->bind_param("si",$fields->name,$id);
+ if ($stmt->execute()) {
+ $this->redis->hSet("device:".$id,"name",$fields->name);
+ } else $success = false;
+ $stmt->close();
+ }
+
+ if (isset($fields->description)) {
+ if (preg_replace('/[^\p{N}\p{L}_\s-:]/u','',$fields->description)!=$fields->description) return array('success'=>false, 'message'=>'invalid characters in device description');
+ $stmt = $this->mysqli->prepare("UPDATE device SET description = ? WHERE id = ?");
+ $stmt->bind_param("si",$fields->description,$id);
+ if ($stmt->execute()) {
+ $this->redis->hSet("device:".$id,"description",$fields->description);
+ } else $success = false;
+ $stmt->close();
+ }
- // Repeat this line changing the field name to add fields that can be updated:
- if (isset($fields->name)) $array[] = "`name` = '".preg_replace('/[^\p{L}_\p{N}\s-:]/u','',$fields->name)."'";
- if (isset($fields->description)) $array[] = "`description` = '".preg_replace('/[^\p{L}_\p{N}\s-:]/u','',$fields->description)."'";
- if (isset($fields->nodeid)) $array[] = "`nodeid` = '".preg_replace('/[^\p{L}_\p{N}\s-:]/u','',$fields->nodeid)."'";
+ if (isset($fields->nodeid)) {
+ if (preg_replace('/[^\p{N}\p{L}_\s-:]/u','',$fields->nodeid)!=$fields->nodeid) return array('success'=>false, 'message'=>'invalid characters in device nodeid');
+ $stmt = $this->mysqli->prepare("UPDATE device SET nodeid = ? WHERE id = ?");
+ $stmt->bind_param("si",$fields->nodeid,$id);
+ if ($stmt->execute()) {
+ $this->redis->hSet("device:".$id,"nodeid",$fields->nodeid);
+ } else $success = false;
+ $stmt->close();
+ }
+
+ if (isset($fields->type)) {
+ if (preg_replace('/[^\/\|\,\w\s-:]/','',$fields->type)!=$fields->type) return array('success'=>false, 'message'=>'invalid characters in device type');
+ $stmt = $this->mysqli->prepare("UPDATE device SET type = ? WHERE id = ?");
+ $stmt->bind_param("si",$fields->type,$id);
+ if ($stmt->execute()) {
+ $this->redis->hSet("device:".$id,"type",$fields->type);
+ } else $success = false;
+ $stmt->close();
+ }
+
if (isset($fields->devicekey)) {
- $devicekey = preg_replace('/[^\p{L}_\p{N}\s-:]/u','',$fields->devicekey);
- $result = $this->mysqli->query("SELECT devicekey FROM device WHERE devicekey='$devicekey'");
- if ($result->num_rows > 0)
- {
- return array('success'=>false, 'message'=>'Field devicekey is invalid'); // is duplicate
- }
- $array[] = "`devicekey` = '".$devicekey."'";
+ // 1. Only allow alphanumeric characters
+ if (!ctype_alnum($fields->devicekey)) return array('success'=>false, 'message'=>'invalid characters in device key');
+
+ // 2. Only allow 32 character length
+ if (strlen($fields->devicekey)!=32) return array('success'=>false, 'message'=>'device key must be 32 characters long');
+
+ $stmt = $this->mysqli->prepare("UPDATE device SET devicekey = ? WHERE id = ?");
+ $stmt->bind_param("si",$fields->devicekey,$id);
+ if ($stmt->execute()) {
+ $this->redis->hSet("device:".$id,"devicekey",$fields->devicekey);
+ } else $success = false;
+ $stmt->close();
}
- if (isset($fields->type)) $array[] = "`type` = '".preg_replace('/[^\/\|\,\w\s-:]/','',$fields->type)."'";
- // Convert to a comma seperated string for the mysql query
- $fieldstr = implode(",",$array);
- $this->mysqli->query("UPDATE device SET ".$fieldstr." WHERE `id` = '$id'");
-
- if ($this->mysqli->affected_rows>0){
- if ($this->redis) {
- $result = $this->mysqli->query("SELECT userid FROM device WHERE id='$id'");
- $row = (array) $result->fetch_object();
- if (isset($row['userid']) && $row['userid']) {
- $this->load_to_redis($row['userid']);
- }
- }
+ if ($success) {
return array('success'=>true, 'message'=>'Field updated');
} else {
return array('success'=>false, 'message'=>'Field could not be updated');
}
}
-
- public function get_templates()
- {
- $devices = array();
- $devices = $this->load_devices_template();
- return $devices;
- }
-
- private function load_devices_template() {
- $list = array();
- foreach (glob("Modules/device/data/*.json") as $file) {
- $content = json_decode(file_get_contents($file));
- $list[basename($file, ".json")] = $content;
+
+ public function set_new_devicekey($id) {
+ $id = intval($id);
+ if (!$this->exist($id)) {
+ if (!$this->redis || !$this->load_device_to_redis($id)) {
+ return array('success'=>false, 'message'=>'Device does not exist');
+ }
+ }
+
+ $devicekey = md5(uniqid(mt_rand(), true));
+
+ $stmt = $this->mysqli->prepare("UPDATE device SET devicekey = ? WHERE id = ?");
+ $stmt->bind_param("si",$devicekey,$id);
+ $result = $stmt->execute();
+ $stmt->close();
+
+ if ($result) {
+ $this->redis->hSet("device:".$id,"devicekey",$devicekey);
+ return $devicekey;
+ } else {
+ return false;
}
- return $list;
}
- public function init_template($id)
- {
- $id = (int) $id;
- if (!$this->exist($id)) return array('success'=>false, 'message'=>'Device does not exist');
-
- $result = $this->mysqli->query("SELECT * FROM device WHERE id = '$id'");
- $row = (array) $result->fetch_object();
-
- if (isset($row['type']) && $row['type']) {
- $file = "Modules/device/data/".$row['type'].".json";
- if (file_exists($file)) {
- $template = json_decode(file_get_contents($file));
- } else {
- return array('success'=>false, 'message'=>"Template file not found '" . $file . "'");
+ public function get_template_list_meta($userid) {
+ $templates = array();
+
+ if ($this->redis) {
+ if (!$this->redis->exists("device:templates:meta")) $this->load_template_list($userid);
+
+ $ids = $this->redis->sMembers("device:templates:meta");
+ foreach ($ids as $id) {
+ $template = $this->redis->hGetAll("device:template:$id");
+ $template["control"] = (bool) $template["control"];
+
+ $templates[$id] = $template;
}
-
- $userid = $row['userid'];
- $node = $row['nodeid'];
- $feeds = $template->feeds;
- $inputs = $template->inputs;
-
- // Create feeds
- $result = $this->create_feeds($userid, $node, $feeds);
- if ($result["success"] !== true) {
- return array('success'=>false, 'message'=>'Error while creating the feeds. ' . $result['message']);
+ }
+ else {
+ if (empty($this->templates)) { // Cache it now
+ $this->load_template_list($userid);
}
+ $templates = $this->templates;
+ }
+ ksort($templates);
+ return $templates;
+ }
- // Create inputs
- $result = $this->create_inputs($userid, $node, $inputs);
- if ($result !== true) {
- return array('success'=>false, 'message'=>'Error while creating the inputs.');
+ private function get_template_meta($userid, $id) {
+ if ($this->redis) {
+ if ($this->redis->exists("device:template:$id")) {
+ $template = $this->redis->hGetAll("device:template:$id");
+ $template["control"] = (bool) $template["control"];
+
+ return $template;
}
-
- // Create inputs processes
- $result = $this->create_inputs_processes($feeds, $inputs);
- if ($result["success"] !== true) {
- return array('success'=>false, 'message'=>'Error while creating the inputs process list. ' . $result['message']);
+ }
+ else {
+ if (empty($this->templates)) { // Cache it now
+ $this->load_template_list($userid);
}
-
- // Create feeds processes
- $result = $this->create_feeds_processes($feeds, $inputs);
- if ($result["success"] !== true) {
- return array('success'=>false, 'message'=>'Error while creating the feeds process list. ' . $result['message']);
+ if(isset($this->templates[$id])) {
+ return $this->templates[$id];
}
}
- return array('success'=>true, 'message'=>'Device initialized');
+ return array('success'=>false, 'message'=>'Device template does not exist');
}
- // Create the feeds
- private function create_feeds($userid, $node, &$feedArray) {
- global $feed_settings;
+ public function get_template_list($userid) {
+ return $this->load_template_list($userid);
+ }
- require_once "Modules/feed/feed_model.php";
- $feed = new Feed($this->mysqli,$this->redis,$feed_settings);
+ public function get_template($userid, $id) {
+ $userid = intval($userid);
+
+ $result = $this->get_template_meta($userid, $id);
+ if (isset($result['success']) && !$result['success']) {
+ return $result;
+ }
+ $module = $result['module'];
+ $class = $this->get_module_class($module, self::TEMPLATE);
+ if ($class != null) {
+ return $class->get_template($userid, $id);
+ }
+ return array('success'=>false, 'message'=>'Unknown error while loading device template details');
+ }
- foreach($feedArray as $f) {
- // Create each feed
- $name = $f->name;
- if (property_exists($f, "tag")) {
- $tag = $f->tag;
- } else {
- $tag = $node;
- }
- $datatype = constant($f->type); // DataType::
- $engine = constant($f->engine); // Engine::
- $options_in = new stdClass();
- if (property_exists($f, "interval")) {
- $options_in->interval = $f->interval;
- }
- $this->log->info("create_feeds() userid=$userid tag=$tag name=$name datatype=$datatype engine=$engine");
- $result = $feed->create($userid,$tag,$name,$datatype,$engine,$options_in);
- if($result["success"] !== true) {
+ public function prepare_template($id) {
+ $id = intval($id);
+
+ $device = $this->get($id);
+ if (isset($device['type']) && $device['type'] != 'null' && $device['type']) {
+ $result = $this->get_template_meta($device['userid'], $device['type']);
+ if (isset($result['success']) && !$result['success']) {
return $result;
}
- $f->feedId = $result["feedid"]; // Assign the created feed id to the feeds array
+ $module = $result['module'];
+ $class = $this->get_module_class($module, self::TEMPLATE);
+ if ($class != null) {
+ return $class->prepare_template($device);
+ }
+ return array('success'=>false, 'message'=>'Device template class is not defined');
}
- return $result;
+ return array('success'=>false, 'message'=>'Device type not specified');
}
- // Create the inputs
- private function create_inputs($userid, $node, &$inputArray) {
- require_once "Modules/input/input_model.php";
- $input = new Input($this->mysqli,$this->redis, null);
-
- foreach($inputArray as $i) {
- // Create each input
- $name = $i->name;
- $description = $i->description;
- if(property_exists($i, "node")) {
- $nodeid = $i->node;
- } else {
- $nodeid = $node;
- }
-
- $inputId = $input->exists_nodeid_name($userid,$nodeid,$name);
-
- if ($inputId==false) {
- $this->log->info("create_inputs() userid=$userid nodeid=$nodeid name=$name description=$description");
- $inputId = $input->create_input($userid, $nodeid, $name);
- if(!$input->exists($inputId)) {
- return false;
- }
- $input->set_fields($inputId, '{"description":"'.$description.'"}');
- }
- $i->inputId = $inputId; // Assign the created input id to the inputs array
+ public function init($id, $template) {
+ $id = intval($id);
+
+ $device = $this->get($id);
+ $result = $this->init_template($device, $template);
+ if (isset($result) && !$result['success']) {
+ return $result;
}
- return true;
+ return array('success'=>true, 'message'=>'Device initialized');
}
- // Create the inputs process lists
- private function create_inputs_processes($feedArray, $inputArray) {
- require_once "Modules/input/input_model.php";
- $input = new Input($this->mysqli,$this->redis, null);
-
- foreach($inputArray as $i) {
- // for each input
- if (isset($i->processList)) {
- $inputId = $i->inputId;
- $result = $this->convertTemplateProcessList($feedArray, $inputArray, $i->processList);
- if (isset($result["success"])) {
- return $result; // success is only filled if it was an error
- }
-
- $processes = implode(",", $result);
- if ($processes != "") {
- $this->log->info("create_inputs_processes() calling input->set_processlist inputId=$inputId processes=$processes");
- $input->set_processlist($inputId, $processes);
- }
+ public function init_template($device, $template) {
+ if (isset($template)) $template = json_decode($template);
+
+ if (isset($device['type']) && $device['type'] != 'null' && $device['type']) {
+ $result = $this->get_template_meta($device['userid'], $device['type']);
+ if (isset($result['success']) && !$result['success']) {
+ return $result;
+ }
+ $module = $result['module'];
+ $class = $this->get_module_class($module, self::TEMPLATE);
+ if ($class != null) {
+ return $class->init_template($device, $template);
}
+ return array('success'=>false, 'message'=>'Device template class is not defined');
}
-
- return array('success'=>true);
+ return array('success'=>false, 'message'=>'Device type not specified');
}
- private function create_feeds_processes($feedArray, $inputArray) {
- global $feed_settings;
-
- require_once "Modules/feed/feed_model.php";
- $feed = new Feed($this->mysqli,$this->redis,$feed_settings);
-
- foreach($feedArray as $f) {
- // for each feed
- if (($f->engine == Engine::VIRTUALFEED) && isset($f->processList)) {
- $feedId = $f->feedId;
- $result = $this->convertTemplateProcessList($feedArray, $inputArray, $f->processList);
- if (isset($result["success"])) {
- return $result; // success is only filled if it was an error
- }
-
- $processes = implode(",", $result);
- if ($processes != "") {
- $this->log->info("create_feeds_processes() calling feed->set_processlist feedId=$feedId processes=$processes");
- $feed->set_processlist($feedId, $processes);
- }
- }
+ public function reload_template_list($userid) {
+ $userid = intval($userid);
+
+ $templates = $this->load_template_list($userid);
+ if (isset($templates) && count($templates) > 0) {
+ return array('success'=>true, 'message'=>'Templates successfully reloaded');
}
-
- return array('success'=>true);
+ return array('success'=>false, 'message'=>'Unknown error while reloading templates');
}
-
- // Converts template processList
- private function convertTemplateProcessList($feedArray, $inputArray, $processArray){
- $resultProcesslist = array();
- if (is_array($processArray)) {
- require_once "Modules/process/process_model.php";
- $process = new Process(null,null,null,null);
- $process_list = $process->get_process_list(); // emoncms supported processes
-
- // create each processlist
- foreach($processArray as $p) {
- $proc_name = $p->process;
- if (!isset($process_list[$proc_name])) {
- $this->log->error("convertProcess() Process '$proc_name' not supported. Module missing?");
- return array('success'=>false, 'message'=>"Process '$proc_name' not supported. Module missing?");
- }
- // Arguments
- if(isset($p->arguments)) {
- if(isset($p->arguments->type)) {
- $type = @constant($p->arguments->type); // ProcessArg::
- $process_type = $process_list[$proc_name][1]; // get emoncms process ProcessArg
-
- if ($process_type != $type) {
- $this->log->error("convertProcess() Bad device template. Missmatch ProcessArg type. Got '$type' expected '$process_type'. process='$proc_name' type='".$p->arguments->type."'");
- return array('success'=>false, 'message'=>"Bad device template. Missmatch ProcessArg type. Got '$type' expected '$process_type'. process='$proc_name' type='".$p->arguments->type."'");
- }
-
- if (isset($p->arguments->value)) {
- $value = $p->arguments->value;
- } else {
- $this->log->error("convertProcess() Bad device template. Undefined argument value. process='$proc_name' type='".$p->arguments->type."'");
- return array('success'=>false, 'message'=>"Bad device template. Undefined argument value. process='$proc_name' type='".$p->arguments->type."'");
- }
-
- if ($type === ProcessArg::VALUE) {
- } else if ($type === ProcessArg::INPUTID) {
- $temp = $this->searchArray($inputArray,'name',$value); // return input array that matches $inputArray[]['name']=$value
- if ($temp->inputId > 0) {
- $value = $temp->inputId;
- } else {
- $this->log->error("convertProcess() Bad device template. Input name '$value' was not found. process='$proc_name' type='".$p->arguments->type."'");
- return array('success'=>false, 'message'=>"Bad device template. Input name '$value' was not found. process='$proc_name' type='".$p->arguments->type."'");
- }
- } else if ($type === ProcessArg::FEEDID) {
- $temp = $this->searchArray($feedArray,'name',$value); // return feed array that matches $feedArray[]['name']=$value
- if ($temp->feedId > 0) {
- $value = $temp->feedId;
- } else {
- $this->log->error("convertProcess() Bad device template. Feed name '$value' was not found. process='$proc_name' type='".$p->arguments->type."'");
- return array('success'=>false, 'message'=>"Bad device template. Feed name '$value' was not found. process='$proc_name' type='".$p->arguments->type."'");
- }
- } else if ($type === ProcessArg::NONE) {
- $value = 0;
- } else if ($type === ProcessArg::TEXT) {
-// } else if ($type === ProcessArg::SCHEDULEID) { //not supporte for now
- } else {
- $this->log->error("convertProcess() Bad device template. Unsuported argument type. process='$proc_name' type='".$p->arguments->type."'");
- return array('success'=>false, 'message'=>"Bad device template. Unsuported argument type. process='$proc_name' type='".$p->arguments->type."'");
- }
-
- } else {
- $this->log->error("convertProcess() Bad device template. Argument type is missing, set to NONE if not required. process='$proc_name' type='".$p->arguments->type."'");
- return array('success'=>false, 'message'=>"Bad device template. Argument type is missing, set to NONE if not required. process='$proc_name' type='".$p->arguments->type."'");
+ private function load_template_list($userid) {
+ $userid = intval($userid);
+
+ if ($this->redis) {
+ foreach ($this->redis->sMembers("device:templates:meta") as $id) {
+ $this->redis->del("device:template:$id");
+ }
+ $this->redis->del("device:templates:meta");
+ }
+ else {
+ $this->templates = array();
+ }
+ $templates = array();
+
+ $dir = scandir("Modules");
+ for ($i=2; $iget_module_class($dir[$i], self::TEMPLATE);
+ if ($class != null) {
+ $module_templates = $class->get_template_list($userid);
+ foreach($module_templates as $key => $value) {
+ $this->cache_template($dir[$i], $key, $value);
+ $templates[$key] = $value;
}
-
- $this->log->info("convertProcess() process process='$proc_name' type='".$p->arguments->type."' value='" . $value . "'");
- $resultProcesslist[] = $proc_name.":".$value;
-
- } else {
- $this->log->error("convertProcess() Bad device template. Missing processlist arguments. process='$proc_name'");
- return array('success'=>false, 'message'=>"Bad device template. Missing processlist arguments. process='$proc_name'");
}
}
}
- return $resultProcesslist;
+
+ return $templates;
+ }
+
+ private function cache_template($module, $id, $template) {
+ $meta = array(
+ "module"=>$module
+ );
+ $meta["name"] = ((!isset($template->name) || $template->name == "" ) ? $id : $template->name);
+ $meta["category"] = ((!isset($template->category) || $template->category== "" ) ? "General" : $template->category);
+ $meta["group"] = ((!isset($template->group) || $template->group== "" ) ? "Miscellaneous" : $template->group);
+ $meta["description"] = (!isset($template->description) ? "" : $template->description);
+ $meta["control"] = (!isset($template->control) ? false : true);
+
+ if ($this->redis) {
+ $this->redis->sAdd("device:templates:meta", $id);
+ $this->redis->hMSet("device:template:$id", $meta);
+ }
+ else {
+ $this->templates[$id] = $meta;
+ }
}
- private function searchArray($array, $key, $val) {
- foreach ($array as $item)
- if (isset($item->$key) && $item->$key == $val)
- return $item;
- return null;
+ private function get_module_class($module, $type) {
+ /*
+ magic function __call (above) MUST BE USED with this.
+ Load additional template module files.
+ Looks in the folder Modules/modulename/ for a file modulename_template.php
+ (module_name all lowercase but class ModulenameTemplate in php file that is CamelCase)
+ */
+ $module_file = "Modules/".$module."/".$module."_".$type.".php";
+ $module_class = null;
+ if(file_exists($module_file)){
+ require_once($module_file);
+
+ $module_class_name = ucfirst(strtolower($module)).ucfirst($type);
+ $module_class = new $module_class_name($this);
+ }
+ return $module_class;
}
}
diff --git a/device_schema.php b/device_schema.php
index 3f5e403..3b44a78 100644
--- a/device_schema.php
+++ b/device_schema.php
@@ -1,12 +1,12 @@
array('type' => 'int(11)', 'Null'=>'NO', 'Key'=>'PRI', 'Extra'=>'auto_increment'),
+ 'id' => array('type' => 'int(11)', 'Null'=>false, 'Key'=>'PRI', 'Extra'=>'auto_increment'),
'userid' => array('type' => 'int(11)'),
+ 'nodeid' => array('type' => 'text'),
'name' => array('type' => 'text', 'default'=>''),
'description' => array('type' => 'text','default'=>''),
- 'type' => array('type' => 'varchar(32)'),
- 'nodeid' => array('type' => 'text'),
- 'devicekey' => array('type' => 'varchar(64)'),
- 'time' => array('type' => 'int(10)')
-);
\ No newline at end of file
+ 'type' => array('type' => 'varchar(32)'),
+ 'devicekey' => array('type' => 'varchar(64)'),
+ 'time' => array('type' => 'int(10)')
+);
diff --git a/device_template.php b/device_template.php
new file mode 100644
index 0000000..984a18d
--- /dev/null
+++ b/device_template.php
@@ -0,0 +1,529 @@
+mysqli = &$parent->mysqli;
+ $this->redis = &$parent->redis;
+ $this->log = new EmonLogger(__FILE__);
+ }
+
+ public function get_template_list($userid) {
+ return $this->load_template_list($userid);
+ }
+
+ protected function load_template_list($userid) {
+ $list = array();
+
+ $iti = new RecursiveDirectoryIterator("Modules/device/data");
+ foreach(new RecursiveIteratorIterator($iti) as $file){
+ if(strpos($file ,".json") !== false){
+ $content = json_decode(file_get_contents($file));
+ $list[basename($file, ".json")] = $content;
+ }
+ }
+ return $list;
+ }
+
+ public function get_template($userid, $type) {
+ $type = preg_replace('/[^\p{L}_\p{N}\s-:]/u','', $type);
+ $list = $this->load_template_list($userid);
+ if (!isset($list[$type])) {
+ return array('success'=>false, 'message'=>'Device template "'.$type.'" not found');
+ }
+ return $list[$type];
+ }
+
+ public function prepare_template($device) {
+ $userid = intval($device['userid']);
+
+ $result = $this->get_template($userid, $device['type']);
+ if (!is_object($result)) {
+ return $result;
+ }
+ $prefix = $this->parse_prefix($device['nodeid'], $device['name'], $result);
+
+ if (isset($result->feeds)) {
+ $feeds = $result->feeds;
+ $this->prepare_feeds($userid, $device['nodeid'], $prefix, $feeds);
+ }
+ else {
+ $feeds = [];
+ }
+
+ if (isset($result->inputs)) {
+ $inputs = $result->inputs;
+ $this->prepare_inputs($userid, $device['nodeid'], $prefix, $inputs);
+ }
+ else {
+ $inputs = [];
+ }
+
+ if (!empty($feeds)) {
+ $this->prepare_input_processes($userid, $prefix, $feeds, $inputs);
+ }
+ if (!empty($inputs)) {
+ $this->prepare_feed_processes($userid, $prefix, $feeds, $inputs);
+ }
+
+ return array('success'=>true, 'feeds'=>$feeds, 'inputs'=>$inputs);
+ }
+
+ public function init_template($device, $template) {
+ $userid = intval($device['userid']);
+
+ if (empty($template)) {
+ $result = $this->prepare_template($device);
+ if (isset($result["success"]) && !$result["success"]) {
+ return $result;
+ }
+ $template = $result;
+ }
+ if (!is_object($template)) $template = (object) $template;
+
+ if (isset($template->feeds)) {
+ $feeds = $template->feeds;
+ $this->create_feeds($userid, $feeds);
+ }
+ else {
+ $feeds = [];
+ }
+
+ if (isset($template->inputs)) {
+ $inputs = $template->inputs;
+ $this->create_inputs($userid, $inputs);
+ }
+ else {
+ $inputs = [];
+ }
+
+ if (!empty($inputs)) {
+ $this->create_input_processes($userid, $feeds, $inputs);
+ }
+ if (!empty($feeds)) {
+ $this->create_feed_processes($userid, $feeds, $inputs);
+ }
+
+ return array('success'=>true, 'message'=>'Device initialized');
+ }
+
+ protected function prepare_feeds($userid, $nodeid, $prefix, &$feeds) {
+ global $feed_settings;
+
+ require_once "Modules/feed/feed_model.php";
+ $feed = new Feed($this->mysqli, $this->redis, $feed_settings);
+
+ foreach($feeds as $f) {
+ $f->name = $prefix.$f->name;
+ if (!isset($f->tag)) {
+ $f->tag = $nodeid;
+ }
+
+ $feedid = $feed->exists_tag_name($userid, $f->tag, $f->name);
+ if ($feedid == false) {
+ $f->action = 'create';
+ $f->id = -1;
+ }
+ else {
+ $f->action = 'none';
+ $f->id = $feedid;
+ }
+ }
+ }
+
+ protected function prepare_inputs($userid, $nodeid, $prefix, &$inputs) {
+ require_once "Modules/input/input_model.php";
+ $input = new Input($this->mysqli, $this->redis, null);
+
+ foreach($inputs as $i) {
+ $i->name = $prefix.$i->name;
+ if(!isset($i->node)) {
+ $i->node = $nodeid;
+ }
+
+ $inputid = $input->exists_nodeid_name($userid, $i->node, $i->name);
+ if ($inputid == false) {
+ $i->action = 'create';
+ $i->id = -1;
+ }
+ else {
+ $i->action = 'none';
+ $i->id = $inputid;
+ }
+ }
+ }
+
+ // Prepare the input process lists
+ protected function prepare_input_processes($userid, $prefix, $feeds, &$inputs) {
+ global $user, $feed_settings;
+
+ require_once "Modules/feed/feed_model.php";
+ $feed = new Feed($this->mysqli, $this->redis, $feed_settings);
+
+ require_once "Modules/input/input_model.php";
+ $input = new Input($this->mysqli, $this->redis, $feed);
+
+ require_once "Modules/process/process_model.php";
+ $process = new Process($this->mysqli, $input, $feed, $user->get_timezone($userid));
+ $process_list = $process->get_process_list(); // emoncms supported processes
+
+ foreach($inputs as $i) {
+ // for each input
+ if (isset($i->id) && (isset($i->processList) || isset($i->processlist))) {
+ $processes = isset($i->processList) ? $i->processList : $i->processlist;
+ if (!empty($processes)) {
+ $processes = $this->prepare_processes($prefix, $feeds, $inputs, $processes, $process_list);
+ if (isset($i->action) && $i->action != 'create') {
+ $processes_input = $input->get_processlist($i->id);
+ if (!isset($processes['success'])) {
+ if ($processes_input == '' && $processes != '') {
+ $i->action = 'set';
+ }
+ else if ($processes_input != $processes) {
+ $i->action = 'override';
+ }
+ }
+ else {
+ if ($processes_input == '') {
+ $i->action = 'set';
+ }
+ else {
+ $i->action = 'override';
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Prepare the feed process lists
+ protected function prepare_feed_processes($userid, $prefix, &$feeds, $inputs) {
+ global $user, $feed_settings;
+
+ require_once "Modules/feed/feed_model.php";
+ $feed = new Feed($this->mysqli, $this->redis, $feed_settings);
+
+ require_once "Modules/input/input_model.php";
+ $input = new Input($this->mysqli, $this->redis, $feed);
+
+ require_once "Modules/process/process_model.php";
+ $process = new Process($this->mysqli, $input, $feed, $user->get_timezone($userid));
+ $process_list = $process->get_process_list(); // emoncms supported processes
+
+ foreach($feeds as $f) {
+ // for each feed
+ if ($f->engine == Engine::VIRTUALFEED && isset($f->id) && (isset($f->processList) || isset($f->processlist))) {
+ $processes = isset($f->processList) ? $f->processList : $f->processlist;
+ if (!empty($processes)) {
+ $processes = $this->prepare_processes($prefix, $feeds, $inputs, $processes, $process_list);
+ if (isset($f->action) && $f->action != 'create') {
+ $processes_input = $feed->get_processlist($f->id);
+ if (!isset($processes['success'])) {
+ if ($processes_input == '' && $processes != '') {
+ $f->action = 'set';
+ }
+ else if ($processes_input != $processes) {
+ $f->action = 'override';
+ }
+ }
+ else {
+ if ($processes_input == '') {
+ $f->action = 'set';
+ }
+ else {
+ $f->action = 'override';
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Prepare template processes
+ protected function prepare_processes($prefix, $feeds, $inputs, &$processes, $process_list) {
+ $process_list_by_name = array();
+ foreach ($process_list as $process_id => $process_item) {
+ $name = $process_item[2];
+ $process_list_by_name[$name] = $process_id;
+ }
+ $processes_converted = array();
+
+ $failed = false;
+ foreach($processes as &$process) {
+ // If process names are used map to process id
+ if (isset($process_list_by_name[$process->process])) $process->process = $process_list_by_name[$process->process];
+
+ $process_id = $process->process;
+ if (!isset($process_list[$process_id])) {
+ $this->log->error("prepare_processes() Process '$process_id' not supported. Module missing?");
+ return array('success'=>false, 'message'=>"Process '$process_id' not supported. Module missing?");
+ }
+
+ $process->name = $process_list[$process->process][0];
+
+ // Arguments
+ if(isset($process->arguments)) {
+ if(isset($process->arguments->type)) {
+ $process->arguments->type = @constant($process->arguments->type); // ProcessArg::
+ $process_type = $process_list[$process_id][1]; // get emoncms process ProcessArg
+
+ if ($process_type != $process->arguments->type) {
+ $this->log->error("prepare_processes() Bad device template. Missmatch ProcessArg type. Got '$process->arguments->type' expected '$process_type'. process='$process_id'");
+ return array('success'=>false, 'message'=>"Bad device template. Missmatch ProcessArg type. Got '$process->arguments->type' expected '$process_type'. process='$process_id'");
+ }
+ else if ($process->arguments->type === ProcessArg::INPUTID || $process->arguments->type === ProcessArg::FEEDID) {
+ $process->arguments->value = $prefix.$process->arguments->value;
+ }
+
+ $result = $this->convert_process($feeds, $inputs, $process);
+ if (isset($result["success"])) {
+ $failed = true;
+ }
+ else {
+ $processes_converted[] = $result;
+ }
+ }
+ else {
+ $this->log->error("prepare_processes() Bad device template. Argument type is missing, set to NONE if not required. process='$process->process' type='".$process->arguments->type."'");
+ return array('success'=>false, 'message'=>"Bad device template. Argument type is missing, set to NONE if not required. process='$process->process' type='".$process->arguments->type."'");
+ }
+ }
+ else {
+ $this->log->error("prepare_processes() Bad device template. Missing processList arguments. process='$process->process'");
+ return array('success'=>false, 'message'=>"Bad device template. Missing processList arguments. process='$process->process'");
+ }
+ }
+ if (!$failed) {
+ return implode(",", $processes_converted);
+ }
+ return array('success'=>false, 'message'=>"Unable to convert all prepared processes");
+ }
+
+ // Create the feeds
+ protected function create_feeds($userid, &$feeds) {
+ global $feed_settings;
+
+ require_once "Modules/feed/feed_model.php";
+ $feed = new Feed($this->mysqli, $this->redis, $feed_settings);
+
+ foreach($feeds as $f) {
+ $datatype = constant($f->type); // DataType::
+ $engine = constant($f->engine); // Engine::
+ $options = new stdClass();
+ if (property_exists($f, "interval")) {
+ $options->interval = $f->interval;
+ }
+
+ if ($f->action === 'create') {
+ $this->log->info("create_feeds() userid=$userid tag=$f->tag name=$f->name datatype=$datatype engine=$engine");
+
+ $result = $feed->create($userid, $f->tag, $f->name, $datatype, $engine, $options);
+ if($result["success"] !== true) {
+ $this->log->error("create_feeds() failed for userid=$userid tag=$f->tag name=$f->name datatype=$datatype engine=$engine");
+ }
+ else {
+ $f->id = $result["feedid"]; // Assign the created feed id to the feeds array
+ }
+ }
+ }
+ }
+
+ // Create the inputs
+ protected function create_inputs($userid, &$inputs) {
+ require_once "Modules/input/input_model.php";
+ $input = new Input($this->mysqli, $this->redis, null);
+
+ foreach($inputs as $i) {
+ if ($i->action === 'create') {
+ $this->log->info("create_inputs() userid=$userid nodeid=$i->node name=$i->name description=$i->description");
+
+ $inputid = $input->create_input($userid, $i->node, $i->name);
+ if(!$input->exists($inputid)) {
+ $this->log->error("create_inputs() failed for userid=$userid nodeid=$i->node name=$i->name description=$i->description");
+ }
+ else {
+ $input->set_fields($inputid, '{"description":"'.$i->description.'"}');
+ $i->id = $inputid; // Assign the created input id to the inputs array
+ }
+ }
+ }
+ }
+
+ // Create the input process lists
+ protected function create_input_processes($userid, $feeds, $inputs) {
+ global $user, $feed_settings;
+
+ require_once "Modules/feed/feed_model.php";
+ $feed = new Feed($this->mysqli, $this->redis, $feed_settings);
+
+ require_once "Modules/input/input_model.php";
+ $input = new Input($this->mysqli, $this->redis, $feed);
+
+ require_once "Modules/process/process_model.php";
+ $process = new Process($this->mysqli, $input, $feed, $user->get_timezone($userid));
+ $process_list = $process->get_process_list(); // emoncms supported processes
+
+ foreach($inputs as $i) {
+ if ($i->action !== 'none') {
+ if (isset($i->id) && (isset($i->processList) || isset($i->processlist))) {
+ $processes = isset($i->processList) ? $i->processList : $i->processlist;
+ $inputid = $i->id;
+
+ if (is_array($processes)) {
+ $processes_converted = array();
+
+ $failed = false;
+ foreach($processes as $process) {
+ $result = $this->convert_process($feeds, $inputs, $process);
+ if (isset($result["success"])) {
+ $failed = true;
+ break;
+ }
+ $processes_converted[] = $result;
+ }
+ $processes = implode(",", $processes_converted);
+ if (!$failed && $processes != "") {
+ $this->log->info("create_inputs_processes() calling input->set_processlist inputid=$inputid processes=$processes");
+ $input->set_processlist($userid, $inputid, $processes, $process_list);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Create the feed process lists
+ protected function create_feed_processes($userid, $feeds, $inputs) {
+ global $user, $feed_settings;
+
+ require_once "Modules/feed/feed_model.php";
+ $feed = new Feed($this->mysqli, $this->redis, $feed_settings);
+
+ require_once "Modules/input/input_model.php";
+ $input = new Input($this->mysqli, $this->redis, $feed);
+
+ require_once "Modules/process/process_model.php";
+ $process = new Process($this->mysqli, $input, $feed, $user->get_timezone($userid));
+ $process_list = $process->get_process_list(); // emoncms supported processes
+
+ foreach($feeds as $f) {
+ if ($f->action !== 'none') {
+ if ($f->engine == Engine::VIRTUALFEED && isset($f->id) && (isset($f->processList) || isset($f->processlist))) {
+ $processes = isset($f->processList) ? $f->processList : $f->processlist;
+ $feedid = $f->id;
+
+ if (is_array($processes)) {
+ $processes_converted = array();
+
+ $failed = false;
+ foreach($processes as $process) {
+ $result = $this->convert_process($feeds, $inputs, $process);
+ if (isset($result["success"])) {
+ $failed = true;
+ break;
+ }
+ $processes_converted[] = $result;
+ }
+ $processes = implode(",", $processes_converted);
+ if (!$failed && $processes != "") {
+ $this->log->info("create_feeds_processes() calling feed->set_processlist feedId=$feedid processes=$processes");
+ $feed->set_processlist($userid, $feedid, $processes, $process_list);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Converts template process
+ protected function convert_process($feeds, $inputs, $process) {
+ if (isset($process->arguments->value)) {
+ $value = $process->arguments->value;
+ }
+ else if ($process->arguments->type === ProcessArg::NONE) {
+ $value = 0;
+ }
+ else {
+ $this->log->error("convertProcess() Bad device template. Undefined argument value. process='$process->process' type='".$process->arguments->type."'");
+ return array('success'=>false, 'message'=>"Bad device template. Undefined argument value. process='$process->process' type='".$process->arguments->type."'");
+ }
+
+ if ($process->arguments->type === ProcessArg::VALUE) {
+ }
+ else if ($process->arguments->type === ProcessArg::INPUTID) {
+ $temp = $this->search_array($inputs, 'name', $value); // return input array that matches $inputArray[]['name']=$value
+ if (isset($temp->id) && $temp->id > 0) {
+ $value = $temp->id;
+ }
+ else {
+ $this->log->info("convertProcess() Input name '$value' was not found. process='$process->process' type='".$process->arguments->type."'");
+ return array('success'=>false, 'message'=>"Input name '$value' was not found. process='$process->process' type='".$process->arguments->type."'");
+ }
+ }
+ else if ($process->arguments->type === ProcessArg::FEEDID) {
+ $temp = $this->search_array($feeds, 'name', $value); // return feed array that matches $feedArray[]['name']=$value
+ if (isset($temp->id) && $temp->id > 0) {
+ $value = $temp->id;
+ }
+ else {
+ $this->log->info("convertProcess() Feed name '$value' was not found. process='$process->process' type='".$process->arguments->type."'");
+ return array('success'=>false, 'message'=>"Feed name '$value' was not found. process='$process->process' type='".$process->arguments->type."'");
+ }
+ }
+ else if ($process->arguments->type === ProcessArg::NONE) {
+ $value = "";
+ }
+ else if ($process->arguments->type === ProcessArg::TEXT) {
+ }
+ else if ($process->arguments->type === ProcessArg::SCHEDULEID) {
+ //not supporte for now
+ }
+ else {
+ $this->log->error("convertProcess() Bad device template. Unsuported argument type. process='$process->process' type='".$process->arguments->type."'");
+ return array('success'=>false, 'message'=>"Bad device template. Unsuported argument type. process='$process->process' type='".$process->arguments->type."'");
+ }
+
+ $this->log->info("convertProcess() process process='$process->process' type='".$process->arguments->type."' value='" . $value . "'");
+ return $process->process.":".$value;
+ }
+
+ protected function parse_prefix($nodeid, $name, $template) {
+ if (isset($template->prefix)) {
+ $prefix = $template->prefix;
+ if ($prefix === "node") {
+ return strtolower($nodeid)."_";
+ }
+ else if ($prefix === "name") {
+ return strtolower($name)."_";
+ }
+ }
+ return "";
+ }
+
+ protected function search_array($array, $key, $val) {
+ foreach ($array as $item) {
+ if (isset($item->$key) && $item->$key == $val) {
+ return $item;
+ }
+ }
+ return null;
+ }
+}
diff --git a/module.json b/module.json
index 31e119e..f60114e 100644
--- a/module.json
+++ b/module.json
@@ -1,4 +1,4 @@
{
"name" : "Device",
- "version" : "1.0.0"
+ "version" : "1.1.0"
}