From 6d04ada06ce29868338face2fbbec8ab72c48dd2 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 15 Oct 2015 18:34:07 +0200 Subject: wip --- diller/README.md | 53 +++++++++++++++++++++------------------------------ diller/inter.lua | 3 ++- diller/main.lua | 13 ++++++++++--- diller/mq.lua | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 87 insertions(+), 40 deletions(-) (limited to 'diller') diff --git a/diller/README.md b/diller/README.md index 322ec45..72d5778 100644 --- a/diller/README.md +++ b/diller/README.md @@ -14,69 +14,60 @@ Is registration required? Can't the firmware just send an update without a value /name (retained) /description (retained) /type TODO: remove? + /status TODO: remove? type specified what the message looks like /firmware For updating the device's firmware -## Device registration flow - - sub: /registration/ - pub: /registration {} - # Diller serial API ## Network settings Request: -Update network settings. If no paramters are given, no changes are done. +Update or query network settings. If no paramters are given, no changes are done. If ip is set to a blank string, it will use DHCP. - network [ip=..] [gateway=..] [ssid=..] + network [ip=..] [gateway=..] [netmask=..] Response: -The command will always return the current values. If the ssid was recently set, the ip, gateway and netmask fields may be missing. +The command will always return the current values. - ok ip=.. gateway=.. netmask=.. ssid=.. + ok ip=.. gateway=.. netmask=.. netmask=.. -## Register property +## Wlan settings Request: - register-property id=.. type=.. name=.. description=.. +Update or query wlan settings. If no paramters are given, no changes are done. -Type examples: - -* `temperature` -* `switch` - boolean switches -* `humidity` -* `rtc` + wlan [ssid=..] [password=..] Response: - ok - -## Publish property value - -Request: - - set-property id=.. [value=..] [name=..] [description=..] +The command will always return the current values. + + ok ssid=.. -Response: +## Set property value - ok +TODO: Implement description? A longer string describing the sensor. -The value might not be updated directly, but may be buffered on the device if it is not yet connected. +Request: -## Publish raw MQTT message + set-property id=.. [value=..] [name=..] -Request: +Type examples: - publish topic=.. [qos=..] [retain=..] - +* `temperature` +* `switch` - boolean switches +* `humidity` +* `rtc` Response: ok +The value might not be updated directly, but may be buffered on the device if it is not yet connected. + ## Reset the device Request: diff --git a/diller/inter.lua b/diller/inter.lua index 725edbd..e10e1df 100644 --- a/diller/inter.lua +++ b/diller/inter.lua @@ -4,7 +4,8 @@ function P.parse(line) -- print("inter_parse: line="..line) line = string.sub(line, 1, string.find(line, "\r")) - line = line:gsub("%s+", "") + line = line:gsub("^%s+", "") + line = line:gsub("%s+$", "") local args = {} local i = string.find(line, " ") diff --git a/diller/main.lua b/diller/main.lua index 112284c..eca88a9 100644 --- a/diller/main.lua +++ b/diller/main.lua @@ -44,14 +44,21 @@ local function on_cmd(cmd, args) if not id then print("fail status=missing-id") else + local name_path = id.."/name" + mq.subscribe(name_path, function() print('message on '..path) end) + + local description_path = id.."/description" + mq.subscribe(description_path, function() print('message on '..path) end) + if args.value then - mq.publish(args.id.."/value", args.value) + local path = id.."/value" + mq.publish(path, args.value) end if args.name then - mq.publish(args.id.."/name", args.name) + mq.publish(name_path, args.name) end if args.description then - mq.publish(args.id.."/description", args.description) + mq.publish(description_path, args.description) end end elseif cmd == "publish" then diff --git a/diller/mq.lua b/diller/mq.lua index 0b4a884..74f3ef8 100644 --- a/diller/mq.lua +++ b/diller/mq.lua @@ -1,12 +1,48 @@ local P = {} local m, topic, cid +local active_subscriptions = {} +local pending_subscriptions = {} +local pending_subcsription local function p(msg) print("MQTT: "..msg) end +-- Subscribe to all registered subscriptions +-- TODO: subscriptions that are not successfull will remain in state = 1. Might not be a real problem if it happens, the server probably disallowed the subscription. +local function create_subscriptions() + print("create_subscriptions, pending count "..table.getn(pending_subscriptions)..", pending: "..tostring(pending_subscription)) + + if (pending_subscription) then + return + end + + pending_subcsription = table.remove(pending_subscriptions) + + -- The API claims that the callback has this signature: function(client, topic, message) + -- but that doesn't seems right from the source code. The code doesn't + -- remember the topics that is being subscribed to. + m:subscribe(pending_subcsription, 0, function(client) + print("success: "..pending_subcsription) + table.insert(active_subscriptions, pending_subscription) + pending_subscription = nil + create_subscriptions() + end) +end + local function mq_client_connected(con) p("connected") + + create_subscriptions() +end + +local function disconnect() + p("Lost wifi connection, disconnecting") + m:close() + m = nil + + -- append active_subscriptions to pending_subscriptions + active_subscriptions = {} end function mq_on_timer() @@ -30,9 +66,7 @@ function mq_on_timer() end else if m then - p("Lost wifi connection, disconnecting") - m:close() - m = nil + disconnect() end end end @@ -45,17 +79,31 @@ function P.init(timer_id, client_id) tmr.alarm(timer_id, 3 * 1000, 1, mq_on_timer) end +function P.subscribe(path, cb) + subscription = subscriptions[path] + if subscription then + print("subscription on "..path.." already registered, state="..tostring(subscription.state)) + return + end + + print("Registering subscription on "..path) + + pending_subscriptions[path] = true + + create_subscriptions() +end + function P.publish(path, payload) if not m then print("Not connected, dropping message to "..path) - return + return false, 'not connected' end path = topic.."/"..path print("path="..path) m:publish(path, payload, 0, 0) - return true, "yo?" + return true, 'ok' end return P -- cgit v1.2.3