Matter support for async HTTP for bridged devices (#18656)

This commit is contained in:
s-hadinger 2023-05-14 23:02:58 +02:00 committed by GitHub
parent 9b8f3b6b4c
commit 951b9b4682
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 4530 additions and 1197 deletions

View File

@ -486,7 +486,7 @@ int be_call_c_func(bvm *vm, const void * func, const char * return_type, const c
} else { // class name
be_find_global_or_module_member(vm, return_type);
be_pushcomptr(vm, (void*) ret); // stack = class, ptr
be_call(vm, 1); // instanciate with 2 arguments, stack = instance, ptr, -1
be_call(vm, 1); // instanciate with 1 argument (ptr)
be_pop(vm, 1); // stack = instance
be_return(vm);
}

View File

@ -133,6 +133,9 @@ extern const bclass be_class_Matter_TLV; // need to declare it upfront because
#include "solidify/solidified_Matter_TLV.h"
#include "solidify/solidified_Matter_IM_Data.h"
#include "solidify/solidified_Matter_UDPServer.h"
#include "solidify/solidified_Matter_TCP_async.h"
#include "solidify/solidified_Matter_HTTP_async.h"
#include "solidify/solidified_Matter_HTTP_remote.h"
#include "solidify/solidified_Matter_Expirable.h"
#include "solidify/solidified_Matter_Fabric.h"
#include "solidify/solidified_Matter_Session.h"
@ -286,6 +289,9 @@ module matter (scope: global, strings: weak) {
// UDP Server
UDPPacket_sent, class(be_class_Matter_UDPPacket_sent)
UDPServer, class(be_class_Matter_UDPServer)
TCP_async, class(be_class_Matter_TCP_async)
HTTP_async, class(be_class_Matter_HTTP_async)
HTTP_remote, class(be_class_Matter_HTTP_remote)
// Expirable
Expirable, class(be_class_Matter_Expirable)

View File

@ -0,0 +1,406 @@
#
# Matter_HTTP_async.be - implements a generic async non-blocking TCP connection
#
# Copyright (C) 2023 Stephan Hadinger & Theo Arends
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#@ solidify:Matter_HTTP_async,weak
# dummy declaration for solidification
class Matter_TCP_async end
class Matter_HTTP_async : Matter_TCP_async
# var addr # remote address
# var port # remote port
# var timeout # timeout in ms
# var tcp # instance of tcpclientasync
# var time_start # timestamp when starting connection
# var tcp_connected # is tcp connected, true/false/nil (nil is in-progress)
var cmd # GET url command
var response # aggrated response
var response_offset # offset to parse in response
var status_code # status code looking for 200
var payload # actual payload of the response (string)
# var status # status, see above
var http_status # status: 0/ in progress, 1/ finished ok, -1/ failed, -2/ timeout
# static var TIMEOUT = 1000 # default timeout: 500ms
var phase # parsing phase: 0/ status line, 1/ headers, 2/ payload chunked
var is_chunked # true if the content is chunked
var chunk_size # nil or int, size of the current chunk
static var HTTP_GET = "GET %s HTTP/1.1\r\nHost %s:%s\r\nConnection: close\r\n\r\n" # see https://stackoverflow.com/questions/6686261/what-at-the-bare-minimum-is-required-for-an-http-request
static var HTTP_STATUS_REGEX = "HTTP/1\\.[1-2] (\\d+) .*?\r\n" # extract stattus code from first line
static var HTTP_HEADER_REGEX = "([A-Za-z0-9-]+): (.*?)\r\n" # extract a header with its 2 parts
static var HTTP_BODY_REGEX = "\r\n" # end of headers
static var HTTP_CHUNK_REGEX = "\r\n([A-Fa-f0-9]+)[ \t]*.*?\r\n" # extract the length of a chunk
static var SPINLOCK = 5 # delay in ms for spinlock
#############################################################
# init
def init(addr, port, timeout, fastloop)
super(self).init(addr, port, timeout, fastloop)
self.compile_re()
end
#############################################################
# compile once for all the regex
def compile_re()
import re
if !global.contains("_re_http_status")
global._re_http_status = re.compile(self.HTTP_STATUS_REGEX)
global._re_http_header = re.compile(self.HTTP_HEADER_REGEX)
global._re_http_body = re.compile(self.HTTP_BODY_REGEX)
global._re_http_chunk = re.compile(self.HTTP_CHUNK_REGEX)
end
end
#############################################################
# begin
#
# returns true if everything is ok, and connection started
# returns false if DNS failed
# returns nil if no network
def begin(cmd)
var ret = super(self).begin()
self.cmd = cmd
return ret
end
#############################################################
# begin_sync
#
# Synchronous (blocking version)
#
# returns nil if something went wrong
# returns the payload as string
def begin_sync(cmd, timeout)
var timeout_old = self.timeout
if timeout != nil self.set_timeout(timeout) end
var payload = nil
var spinlock = self.SPINLOCK
# try
var ret = self.begin(cmd)
if ret # true just means that DNS was ok and that nothing went wrong
while self.http_status == 0
self.loop()
tasmota.delay(spinlock)
end
end
self.set_timeout(timeout_old)
return self.http_status > 0 ? self.payload : nil
end
def reset()
super(self).reset()
# free buffers
self.cmd = nil
self.response = nil
self.response_offset = 0
self.payload = ""
self.phase = 0
self.http_status = 0
self.is_chunked = false
self.chunk_size = nil
end
#############################################################
# parse_http_response
#
# Parse incoming HTTP response from self.response
def parse_http_response()
if self.phase == 0
self.parse_http_status_line()
elif self.phase == 1
self.parse_http_headers()
elif self.phase == 2
self.parse_http_payload()
end
# if phase == 3 (payload raw) we don't parse anything and work for tcp connection to be closed
end
#############################################################
# parse_http_status_line
#
# Parse incoming HTTP status line
def parse_http_status_line()
var m = global._re_http_status.match2(self.response, self.response_offset)
# Ex: [17, '200']
if m
self.response_offset = m[0] # move to following bytes
self.status_code = int(m[1])
self.phase = 1 # proceed to parsing headers
self.parse_http_headers()
elif size(self.response) > 100 # if no match and we still have 100 bytes, then it fails
self.close()
self.status = -4
end
end
#############################################################
# parse_http_status_line
#
# Parse incoming HTTP status line
def parse_http_headers()
while true
# print("parse_http_headers", "self.response_offset=", self.response_offset)
var m = global._re_http_header.match2(self.response, self.response_offset)
# print("m=", m)
# Ex: [32, 'Content-Type', 'application/json']
if m
self.event_http_header(m[1], m[2])
self.response_offset += m[0]
else # no more headers
var m2 = global._re_http_body.match2(self.response, self.response_offset)
if m2
# end of headers
# we keep \r\n which is used by pattern
self.event_http_headers_end() # no more headers
self.phase = 2
self.parse_http_payload() # continue to parsing payload
end
if size(self.response) > 1024 # we don't accept a single header larger than 1KB
self.close()
self.status = -4
self.http_status = -1
self.event_http_failed()
end
return
end
end
end
#############################################################
# parse_http_status_line
#
# Parse incoming HTTP status line
def parse_http_payload()
if self.is_chunked
while true
# if no current chunk size
if self.chunk_size == nil
var m = global._re_http_chunk.match2(self.response, self.response_offset)
if m
self.response_offset += m[0]
self.chunk_size = int('0x'+m[1])
# if chunk size is zero, finished
if self.chunk_size == 0
self.close()
self.status = 2 # finished
self.response = '' # free space
self.response_offset = 0
self.http_status = 1 # ok
self.event_http_finished()
return
end
end
end
# do we have a chunk size
if self.chunk_size != nil
# print("chunk_size", self.chunk_size, size(self.response) - self.response_offset)
if self.chunk_size <= size(self.response) - self.response_offset
# we have a complete chunk in the buffer
self.payload += self.response[self.response_offset .. self.response_offset + self.chunk_size - 1]
self.response = self.response[self.response_offset + self.chunk_size .. ] # truncate to save space
self.response_offset = 0
self.chunk_size = nil
# print(bytes().fromstring(self.response).tohex())
else
return # return until more data is received
end
else
return
end
end
else
# non-chunked
self.payload += self.response[self.response_offset..]
self.response = ""
self.response_offset = 0
end
end
#############################################################
# send_http
#
# Send http request
def send_http()
import string
# "GET %s HTTP/1.1\r\nHost %s:%s\r\nConnection: close\r\n\r\n"
self.response = ""
# special formatting for IPv6
var addr = self.addr
if string.find(addr, ':') >= 0
addr = "[" + addr + "]" # IPv6 must be enclosed in brakets
end
var req = string.format(self.HTTP_GET, self.cmd, addr, self.port)
#print("sending ", req)
var ret = self.write(req)
if ret != size(req)
# print("Could not send","size=",size(req),"ret=",ret)
self.close()
self.status = -4
self.http_status = -1
self.event_http_failed()
end
end
#############################################################
# Events: method should be overriden
#############################################################
# From TCP
# event_established: connection was established
# event_dnsfailed: dns resolution failed
# event_refused: connection was refused by peer
# event_timeout: connection timed out
# event_closed: connection was normally closed (after being established)
# event_available: incoming data is ready to be retrieved with `read()` or `readbytes()`
# event_listening: outgoing buffer is empty, ready to send data with `write()`
# From HTTP
# event_http_status_code: received HTTP status code (stored in `status_code`)
# event_http_header: received HTTP header (not stored except `is_chunked`)
# event_http_headers_end: all HTTP headers received
# Always finishes with one of:
# event_http_finished: HTTP finished, result is in `payload`
# event_http_failed: HTTP connection failed (not a timeout)
# event_http_timeout: HTTP timeout
#############################################################
# event_established
#
# When connection is established, we send the GET request in
# a single write, and we don't need to send anything more
def event_established()
self.send_http()
end
#############################################################
# event_available
#
# Data received
def event_available()
self.receive()
end
#############################################################
# event_http_status_code
#
# Received status_code
def event_http_status_code(status_code, status_message)
self.status_code = status_code
end
#############################################################
# event_http_header
#
# Received header
def event_http_header(header_key, header_value)
import string
header_key = string.tolower(header_key)
header_value = string.tolower(header_value)
# print("header=", header_key, header_value)
if header_key == 'transfer-encoding' && string.tolower(header_value) == 'chunked'
self.is_chunked = true
end
end
#############################################################
# event_http_headers_end
#
# All headers are received
def event_http_headers_end()
# print("event_http_headers_end")
# truncate to save space
if self.response_offset > 0
self.response = self.response[self.response_offset .. ]
self.response_offset = 0
end
end
#############################################################
# receive
#
# Receive and collate
def receive()
if self.tcp_connected != true return end # not connected
if (tasmota.millis() - self.time_start) > self.timeout
# connection timeout
# print("Connected timeout in", tasmota.millis() - self.time_start, "ms")
self.status = -3
self.close()
self.http_status = -2
self.event_http_timeout()
else
var avail = self.tcp.available()
var new_data = 0
while avail > 0
var s = self.tcp.read()
# print("read size=", size(s), "avail=", avail, "in", tasmota.millis() - self.time_start, "ms")
self.response += s
new_data += size(s)
avail = self.tcp.available()
end
if new_data > 0
# print("read size=", new_data, "in", tasmota.millis() - self.time_start, "ms")
self.parse_http_response() # try to parse response
end
end
end
#############################################################
# event_http_finished
#
# Transaction finished sucessfully, result in self.payload
def event_http_finished() end
#############################################################
# event_http_failed
#
# Transaction finished sucessfully, result in self.payload
def event_http_failed() end
def event_refused() self.http_status = -1 self.event_http_failed() end
#############################################################
# event_http_timeout
#
# Transaction finished sucessfully, result in self.payload
def event_http_timeout() end
def event_timeout() self.http_status = -2 self.event_http_timeout() end
end
matter.HTTP_async = Matter_HTTP_async
#-
# Example
tcp = matter.HTTP_async("192.168.2.200", 80, 1000)
tcp.begin("/cm?cmnd=Status%208")
tcp.begin("/")
# Synchronous examples
tcp = matter.HTTP_async("192.168.2.200", 80, 1000)
print(tcp.begin_sync("/cm?cmnd=Status%208", 500))
print(tcp.begin_sync("/", 500))
-#

View File

@ -0,0 +1,87 @@
#
# Matter_HTTP_remote.be - implements an interface to query remotely Tasmota device via HTTP
#
# Copyright (C) 2023 Stephan Hadinger & Theo Arends
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#@ solidify:Matter_HTTP_remote,weak
# dummy declaration for solidification
class Matter_HTTP_async end
class Matter_HTTP_remote : Matter_HTTP_async
var cb # call cb(http_status, payload)
#############################################################
# init
def init(addr, port, timeout, fastloop)
super(self).init(addr, port, timeout, fastloop)
end
def set_cb(cb)
self.cb = cb
end
#############################################################
# begin
#
# returns true if everything is ok, and connection started
# returns false if DNS failed
# returns nil if no network
def begin(cmd)
import string
tasmota.log(string.format("MTR: HTTP async request 'http://%s:%i/%s'", self.addr, self.port, cmd), 3)
return super(self).begin(cmd)
end
#############################################################
# begin_sync
#
# Synchronous (blocking version)
#
# returns nil if something went wrong
# returns the payload as string
def begin_sync(cmd, timeout)
import string
tasmota.log(string.format("MTR: HTTP sync request 'http://%s:%i/%s'", self.addr, self.port, cmd), 3)
return super(self).begin_sync(cmd, timeout)
end
def event_http_finished()
import string
var payload_short = (self.payload != nil) ? self.payload : 'nil'
if size(payload_short) > 30 payload_short = payload_short[0..29] + '...' end
tasmota.log(string.format("MTR: HTTP response in %i ms: '%s'", tasmota.millis() - self.time_start, payload_short), 3)
if self.cb
self.cb(self.http_status, self.payload)
end
end
def event_http_failed()
tasmota.log("MTR: HTTP failed", 3)
if self.cb
self.cb(self.http_status, nil)
end
end
def event_http_timeout()
tasmota.log("MTR: HTTP timeout", 3)
if self.cb
self.cb(self.http_status, nil)
end
end
end
matter.HTTP_remote = Matter_HTTP_remote

View File

@ -66,18 +66,46 @@ class Matter_Plugin
#############################################################
# Stub for updating shadow values (local copies of what we published to the Matter gateway)
def update_shadow()
self.tick = self.device.tick
#
# TO BE OVERRIDDEN
# This call is synnchronous and blocking.
def parse_update(data)
end
#############################################################
# Stub for updating shadow values (local copies of what we published to the Matter gateway)
#
# This method should collect the data from the local or remote device
# and call `parse_update(<data>)` when data is available.
#
# TO BE OVERRIDDEN
# This call is synnchronous and blocking.
def update_shadow()
self.tick = self.device.tick
self.parse_update(nil)
end
#############################################################
# Stub for updating shadow values (local copies of what we published to the Matter gateway)
#
# This call is synnchronous and blocking.
def update_shadow_lazy()
if self.tick != self.device.tick
self.update_shadow()
self.tick = self.device.tick
end
end
#############################################################
# probe_shadow_async
#
# TO BE OVERRIDDEN - DON'T CALL SUPER - default is just calling `update_shadow()`
# This is called on a regular basis, depending on the type of plugin.
# Whenever the data is returned, call `parse_update(<data>)` to update values
def probe_shadow_async()
self.update_shadow()
end
#############################################################
# signal that an attribute has been changed
#
@ -250,7 +278,9 @@ class Matter_Plugin
self.update_next = tasmota.millis(rand31 % self.UPDATE_TIME)
else
if tasmota.time_reached(self.update_next)
self.update_shadow_lazy() # call update_shadow if not already called
if self.tick != self.device.tick
self.probe_shadow_async() # call update_shadow if not already called
end
self.update_next = tasmota.millis(self.UPDATE_TIME) # rearm timer
end
end

View File

@ -30,7 +30,8 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device
static var ARG = "" # additional argument name (or empty if none)
static var ARG_HTTP = "url" # domain name
static var UPDATE_TIME = 3000 # update every 3s
static var HTTP_TIMEOUT = 300 # wait for 300ms max, since we're on LAN
static var PROBE_TIMEOUT = 700 # timeout of 700 ms for probing
static var SYNC_TIMEOUT = 500 # timeout of 700 ms for probing
static var CLUSTERS = {
# 0x001D: inherited # Descriptor Cluster 9.5 p.453
# 0x0003: inherited # Identify 1.2 p.16
@ -44,31 +45,27 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device
}
# static var TYPES = { 0x010A: 2 } # On/Off Light
var tasmota_http # domain name for HTTP, ex: 'http://192.168.1.10/'
var tasmota_status_8 # remote `Status 8` sensor values (last known)
var tasmota_status_11 # remote `Status 11` light values (last known)
# each contain a `_tick` attribute to known when they were last loaded
var reachable # is the device reachable
var reachable_tick # last tick when the reachability was seen (avoids sending superfluous ping commands)
var http_shadow_map # map of shadows
# <x>: map from json - memorize the result from `Status <x>``
# each contain a `_tick` attribute to known when they were last loaded
var http_remote # instance of Matter_HTTP_remote
var next_probe_timestamp # timestamp for next probe (in millis())
#############################################################
# Constructor
def init(device, endpoint, arguments)
import string
super(self).init(device, endpoint, arguments)
var http = arguments.find(self.ARG_HTTP)
if http
if string.find(http, '://') < 0
http = "http://" + http + "/"
end
self.tasmota_http = http
else
tasmota.log(string.format("MTR: ERROR: 'url' is not configured for endpoint %i", endpoint), 2)
end
self.tasmota_status_8 = nil
self.tasmota_status_11 = nil
var addr = arguments.find(self.ARG_HTTP)
self.http_shadow_map = {}
self.reachable = false # force a valid bool value
self.next_probe_timestamp = nil
self.http_remote = matter.HTTP_remote(addr, 80, self.PROBE_TIMEOUT)
self.http_remote.set_cb(/s,p-> self.parse_http_response(s, p))
end
#############################################################
@ -84,36 +81,36 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device
end
#############################################################
# call_remote
# call_remote_async
#
# Call a remote Tasmota device, returns Berry native map or nil
def call_remote(cmd, arg)
if !self.tasmota_http return nil end
import json
# Call a remote Tasmota device, returns nothing, callback is called when data arrives
def call_remote_async(cmd, arg)
import string
if !tasmota.wifi()['up'] && !tasmota.eth()['up'] return nil end # no network
var url = string.format("/cm?cmnd=%s%%20%s", cmd, arg ? arg : '')
var ret = self.http_remote.begin(url, self.PROBE_TIMEOUT)
end
#############################################################
# call_remote_sync
#
# Call a remote Tasmota device, returns Berry native map or nil
def call_remote_sync(cmd, arg)
# if !self.http_remote return nil end
import string
if !tasmota.wifi()['up'] && !tasmota.eth()['up'] return nil end # no network
var retry = 2 # try 2 times if first failed
var url = string.format("/cm?cmnd=%s%%20%s", cmd, arg ? arg : '')
while retry > 0
var cl = webclient()
cl.set_timeouts(1000, 1000)
cl.set_follow_redirects(false)
var url = string.format("%scm?cmnd=%s%%20%s", self.tasmota_http, cmd, arg ? arg : '')
tasmota.log("MTR: HTTP GET "+url, 3)
cl.begin(url)
var r = cl.GET()
tasmota.log("MTR: HTTP GET code=" + str(r), 3)
if r == 200
var s = cl.get_string()
cl.close()
tasmota.log("MTR: HTTP GET payload=" + s, 3)
var j = json.load(s)
var ret = self.http_remote.begin_sync(url, self.SYNC_TIMEOUT)
if ret != nil
# device is known to be reachable
self.reachable = true
self.reachable_tick = self.device.tick
return j
return ret
end
cl.close()
retry -= 1
tasmota.log("MTR: HTTP GET retrying", 3)
end
@ -121,13 +118,54 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device
return nil
end
#############################################################
# parse_http_response
#
# Parse response from HTTP API and update shadows
# We support:
# `Status 8`: {"StatusSNS":{ [...] }}
# `Status 11`: {"StatusSTS":{ [...] }}
# `Status 13`: {"StatusSHT":{ [...] }}
def parse_http_response(status, payload)
if status > 0
# device is known to be reachable
self.reachable = true
var tick = self.device.tick
self.reachable_tick = tick
import json
var j = json.load(payload)
var code = nil # index of Status
if j
# filter
if j.contains("StatusSNS") # Status 8
j = j["StatusSNS"]
code = 8
elif j.contains("StatusSTS") # Status 11
j = j["StatusSTS"]
code = 11
elif j.contains("StatusSHT") # Status 13
j = j["StatusSTS"]
code = 13
end
if code != nil
j['_tick'] = tick
self.http_shadow_map[code] = j
end
# convert to shadow values
self.parse_update(j, code) # call parser
end
end
end
#############################################################
# is_reachable()
#
# Pings the device and checks if it's reachable
def is_reachable()
def is_reachable_sync()
if self.device.tick != self.reachable_tick
var ret = self.call_remote("", "") # empty command works as a ping
var ret = self.call_remote_sync("", "") # empty command works as a ping
self.reachable = (ret != nil)
# self.reachable_tick = cur_tick # done by caller
end
@ -135,43 +173,28 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device
end
#############################################################
# get_status_8()
# get_remote_status_sync()
#
# Get remote `Status 8` values of sensors, and cache for the current tick
def get_status_8()
# Get remote `Status <x>` values of sensors, sync and blocking
def get_remote_status_lazy(x, sync)
var cur_tick = self.device.tick
if self.tasmota_status_8 == nil || self.tasmota_status_8.find("_tick") != cur_tick
var ret = self.call_remote("Status", "8") # call `Status 8`
if ret
ret["_tick"] = cur_tick
self.tasmota_status_8 = ret
return ret
else
return nil
var shadow_x = self.http_shadow_map.find(x)
if shadow_x
if shadow_x.find('_tick') == cur_tick
return shadow_x # we have already updated in this tick
end
else
return self.tasmota_status_8 # return cached value
end
return self.call_remote_sync("Status", str(x))
end
#############################################################
# get_status_11()
# probe_shadow_async
#
# Get remote `Status 11` values of sensors, and cache for the current tick
def get_status_11()
var cur_tick = self.device.tick
if self.tasmota_status_11 == nil || self.tasmota_status_11.find("_tick") != cur_tick
var ret = self.call_remote("Status", "11") # call `Status 8`
if ret
ret["_tick"] = cur_tick
self.tasmota_status_11 = ret
return ret
else
return nil
end
else
return self.tasmota_status_11 # return cached value
end
# ### TO BE OVERRIDDEN - DON'T CALL SUPER - default is just calling `update_shadow()`
# This is called on a regular basis, depending on the type of plugin.
# Whenever the data is returned, call `update_shadow(<data>)` to update values
def probe_shadow_async()
# self.call_remote_async(<cmd>, <data>)
end
#############################################################
@ -188,7 +211,7 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device
if attribute == 0x0000 # ---------- DataModelRevision / CommissioningWindowStatus ----------
# return TLV.create_TLV(TLV.U2, 1)
elif attribute == 0x0011 # ---------- Reachable / bool ----------
return TLV.create_TLV(TLV.BOOL, true) # TODO find a way to do a ping
return TLV.create_TLV(TLV.BOOL, self.reachable) # TODO find a way to do a ping
end
else
@ -207,7 +230,7 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device
var url = str(conf.find(_class.ARG_HTTP, ''))
var arg = s + "," + url
print("MTR: ui_conf_to_string", conf, cl, arg)
# print("MTR: ui_conf_to_string", conf, cl, arg)
return arg
end
@ -220,7 +243,7 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device
var elts = string.split(arg + ',', ',', 3) # add ',' at the end to be sure to have at least 2 arguments
conf[_class.ARG_HTTP] = elts[1]
super(_class).ui_string_to_conf(cl, conf, elts[0])
print("ui_string_to_conf", conf, arg)
# print("ui_string_to_conf", conf, arg)
return conf
end

View File

@ -38,7 +38,6 @@ class Matter_Plugin_Bridge_OnOff : Matter_Plugin_Bridge_HTTP
}
static var TYPES = { 0x010A: 2 } # On/Off Light
var tasmota_http # domain name for HTTP
var tasmota_relay_index # Relay number in Tasmota (zero based)
var shadow_onoff # fake status for now # TODO
@ -56,23 +55,40 @@ class Matter_Plugin_Bridge_OnOff : Matter_Plugin_Bridge_HTTP
# Update shadow
#
def update_shadow()
var st11 = self.get_status_11()
if st11
st11 = st11.find('StatusSTS', {}) # remove first level
var state = (st11.find("POWER") == "ON")
var ret = self.call_remote_sync("Status", "11")
super(self).update_shadow()
end
#############################################################
# Stub for updating shadow values (local copies of what we published to the Matter gateway)
#
# TO BE OVERRIDDEN
# This call is synnchronous and blocking.
def parse_update(data, index)
if index == 11 # Status 11
var state = (data.find("POWER") == "ON")
if self.shadow_onoff != nil && self.shadow_onoff != bool(state)
self.attribute_updated(0x0006, 0x0000)
end
self.shadow_onoff = state
end
super(self).update_shadow()
end
#############################################################
# probe_shadow_async
#
# ### TO BE OVERRIDDEN - DON'T CALL SUPER - default is just calling `update_shadow()`
# This is called on a regular basis, depending on the type of plugin.
# Whenever the data is returned, call `update_shadow(<data>)` to update values
def probe_shadow_async()
self.call_remote_async("Status", "11")
end
#############################################################
# Model
#
def set_onoff(v)
self.call_remote("Power", v ? "1" : "0")
self.call_remote_sync("Power", v ? "1" : "0")
self.update_shadow()
end

View File

@ -0,0 +1,236 @@
#
# Matter_TCP_async.be - implements a generic async non-blocking TCP connection
#
# Copyright (C) 2023 Stephan Hadinger & Theo Arends
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#@ solidify:Matter_TCP_async,weak
# Status:
# nil = uninitialized
# 0 = starting (tcp_connected == nil) - still on-going
# 1 = connected (tcp_connected == true)
# 2 = finished (tcp_connected == false and result in response)
# -1 = DNS failed (tcp_connected == false)
# -2 = refused (tcp_connecetd == false)
# -3 = timeout (tcp_connecetd == false)
# -4 = error communication error
class Matter_TCP_async
var addr # (string) remote address
var port # (int) remote port
var timeout # (int) timeout in ms
var tcp # instance of tcpclientasync
var time_start # (int) timestamp when starting connection
var tcp_connected # (bool or nil) is tcp connected, true/false/nil (nil is in-progress)
var status # (int) status, see above
static var TIMEOUT = 1000 # default timeout: 1000ms
var fast_loop # (opt) either nil or a closure
#############################################################
# constructor
#
# fastloop: (opt) if 'true' uses fastloop instead of every_50ms
def init(addr, port, timeout, fastloop)
if timeout == nil timeout = self.TIMEOUT end
if port == nil port = 80 end
self.addr = str(addr)
self.port = int(port)
self.timeout = timeout
self.tcp = tcpclientasync()
if fastloop
self.fast_loop = / -> self.loop() # create a closure to use with fastloop
end
end
#############################################################
# begin
#
# returns true if everything is ok, and connection started
# returns false if DNS failed
# returns nil if no network
def begin()
self.reset()
if !tasmota.wifi()['up'] && !tasmota.eth()['up'] return nil end # no network
self.time_start = tasmota.millis()
self.status = 0
if (self.tcp.connect(self.addr, self.port))
if self.fast_loop
tasmota.remove_fast_loop(self.fast_loop)
tasmota.add_fast_loop(self.fast_loop)
else
tasmota.add_driver(self)
end
return true
else
import string
tasmota.log(string.format("BRY: failed to resolve [%s]:%i", self.addr, self.port), 3)
self.close()
self.status = -1
self.tcp_connected = false
self.event_dnsfailed()
return false
end
end
#############################################################
# Set a new timeout, or `nil` for default (1s)
def set_timeout(timeout)
if timeout == nil timeout = self.TIMEOUT end
self.timeout = timeout
end
#############################################################
# Reset the instance to send a open a new connection
# This allows to reuse the same object.
def reset()
self.tcp.close()
self.tcp_connected = nil
end
#############################################################
# send_http
def close()
self.tcp.close()
if self.fast_loop
tasmota.remove_fast_loop(self.fast_loop)
else
tasmota.remove_driver(self)
end
# if it was connected, send event
if self.tcp_connected == true
self.event_closed()
end
self.tcp_connected = false
end
def every_50ms()
self.loop()
end
#############################################################
# Main loop, check evolution and trigger events
#############################################################
def loop()
var prev_connected = self.tcp_connected
if self.status == nil self.close() return end # safeguard, this is invalid state
self.tcp_connected = self.tcp.connected()
# if not yet connected, check if we finally got a response
if prev_connected == nil # not yet connected
if self.tcp_connected == true
# we finally got connection
self.status = 1
self.event_established()
# and continue below
elif self.tcp_connected == false
# connection failed
self.status = -2
self.event_refused()
self.close()
return
elif (tasmota.millis() - self.time_start) > self.timeout
# connection timeout
self.status = -3
self.tcp_connected = false # force to false
self.event_timeout()
end
end
if (tasmota.millis() - self.time_start) > self.timeout
self.close()
self.status = -3
self.event_timeout()
return
end
if self.tcp_connected == false
if prev_connected == true
self.event_closed()
end
self.close() # close implicitly removes from loop
return
end
# reading has priority because we don't want to lose data
if self.tcp.available()
self.event_available()
end
# can we send data
if self.tcp.listening()
self.event_listening()
end
end
def write(content)
if self.tcp_connected
return self.tcp.write(content)
end
return 0
end
def read()
if self.tcp_connected
return self.tcp.read()
end
return nil
end
def readbytes()
if self.tcp_connected
return self.tcp.readbytes()
end
return nil
end
def available()
if self.tcp_connected
return self.tcp.available()
end
return 0
end
def listening()
if self.tcp_connected
return self.tcp.listening()
end
return false
end
#############################################################
# Events: method should be overriden
#############################################################
# event_established: connection was established
# event_dnsfailed: dns resolution failed
# event_refused: connection was refused by peer
# event_timeout: connection timed out
# event_closed: connection was normally closed (after being established)
# event_available: incoming data is ready to be retrieved with `read()` or `readbytes()`
# event_listening: outgoing buffer is empty, ready to send data with `write()`
def event_established() end
def event_dnsfailed() end
def event_refused() end
def event_timeout() end
def event_closed() end
def event_available() end
def event_listening() end
end
matter.TCP_async = Matter_TCP_async

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,363 @@
/* Solidification of Matter_HTTP_remote.h */
/********************************************************************\
* Generated code, don't edit *
\********************************************************************/
#include "be_constobj.h"
extern const bclass be_class_Matter_HTTP_remote;
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(Matter_HTTP_remote_init, /* name */
be_nested_proto(
11, /* nstack */
5, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_str_weak(init),
}),
be_str_weak(init),
&be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x60140003, // 0000 GETGBL R5 G3
0x5C180000, // 0001 MOVE R6 R0
0x7C140200, // 0002 CALL R5 1
0x8C140B00, // 0003 GETMET R5 R5 K0
0x5C1C0200, // 0004 MOVE R7 R1
0x5C200400, // 0005 MOVE R8 R2
0x5C240600, // 0006 MOVE R9 R3
0x5C280800, // 0007 MOVE R10 R4
0x7C140A00, // 0008 CALL R5 5
0x80000000, // 0009 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: begin_sync
********************************************************************/
be_local_closure(Matter_HTTP_remote_begin_sync, /* name */
be_nested_proto(
12, /* nstack */
3, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 9]) { /* constants */
/* K0 */ be_nested_str_weak(string),
/* K1 */ be_nested_str_weak(tasmota),
/* K2 */ be_nested_str_weak(log),
/* K3 */ be_nested_str_weak(format),
/* K4 */ be_nested_str_weak(MTR_X3A_X20HTTP_X20sync_X20request_X20_X27http_X3A_X2F_X2F_X25s_X3A_X25i_X2F_X25s_X27),
/* K5 */ be_nested_str_weak(addr),
/* K6 */ be_nested_str_weak(port),
/* K7 */ be_const_int(3),
/* K8 */ be_nested_str_weak(begin_sync),
}),
be_str_weak(begin_sync),
&be_const_str_solidified,
( &(const binstruction[19]) { /* code */
0xA40E0000, // 0000 IMPORT R3 K0
0xB8120200, // 0001 GETNGBL R4 K1
0x8C100902, // 0002 GETMET R4 R4 K2
0x8C180703, // 0003 GETMET R6 R3 K3
0x58200004, // 0004 LDCONST R8 K4
0x88240105, // 0005 GETMBR R9 R0 K5
0x88280106, // 0006 GETMBR R10 R0 K6
0x5C2C0200, // 0007 MOVE R11 R1
0x7C180A00, // 0008 CALL R6 5
0x581C0007, // 0009 LDCONST R7 K7
0x7C100600, // 000A CALL R4 3
0x60100003, // 000B GETGBL R4 G3
0x5C140000, // 000C MOVE R5 R0
0x7C100200, // 000D CALL R4 1
0x8C100908, // 000E GETMET R4 R4 K8
0x5C180200, // 000F MOVE R6 R1
0x5C1C0400, // 0010 MOVE R7 R2
0x7C100600, // 0011 CALL R4 3
0x80040800, // 0012 RET 1 R4
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_http_finished
********************************************************************/
be_local_closure(Matter_HTTP_remote_event_http_finished, /* name */
be_nested_proto(
10, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[14]) { /* constants */
/* K0 */ be_nested_str_weak(string),
/* K1 */ be_nested_str_weak(payload),
/* K2 */ be_nested_str_weak(nil),
/* K3 */ be_const_int(0),
/* K4 */ be_nested_str_weak(_X2E_X2E_X2E),
/* K5 */ be_nested_str_weak(tasmota),
/* K6 */ be_nested_str_weak(log),
/* K7 */ be_nested_str_weak(format),
/* K8 */ be_nested_str_weak(MTR_X3A_X20HTTP_X20response_X20in_X20_X25i_X20ms_X3A_X20_X27_X25s_X27),
/* K9 */ be_nested_str_weak(millis),
/* K10 */ be_nested_str_weak(time_start),
/* K11 */ be_const_int(3),
/* K12 */ be_nested_str_weak(cb),
/* K13 */ be_nested_str_weak(http_status),
}),
be_str_weak(event_http_finished),
&be_const_str_solidified,
( &(const binstruction[39]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x88080101, // 0001 GETMBR R2 R0 K1
0x4C0C0000, // 0002 LDNIL R3
0x20080403, // 0003 NE R2 R2 R3
0x780A0001, // 0004 JMPF R2 #0007
0x88080101, // 0005 GETMBR R2 R0 K1
0x70020000, // 0006 JMP #0008
0x58080002, // 0007 LDCONST R2 K2
0x600C000C, // 0008 GETGBL R3 G12
0x5C100400, // 0009 MOVE R4 R2
0x7C0C0200, // 000A CALL R3 1
0x5412001D, // 000B LDINT R4 30
0x240C0604, // 000C GT R3 R3 R4
0x780E0004, // 000D JMPF R3 #0013
0x540E001C, // 000E LDINT R3 29
0x400E0603, // 000F CONNECT R3 K3 R3
0x940C0403, // 0010 GETIDX R3 R2 R3
0x000C0704, // 0011 ADD R3 R3 K4
0x5C080600, // 0012 MOVE R2 R3
0xB80E0A00, // 0013 GETNGBL R3 K5
0x8C0C0706, // 0014 GETMET R3 R3 K6
0x8C140307, // 0015 GETMET R5 R1 K7
0x581C0008, // 0016 LDCONST R7 K8
0xB8220A00, // 0017 GETNGBL R8 K5
0x8C201109, // 0018 GETMET R8 R8 K9
0x7C200200, // 0019 CALL R8 1
0x8824010A, // 001A GETMBR R9 R0 K10
0x04201009, // 001B SUB R8 R8 R9
0x5C240400, // 001C MOVE R9 R2
0x7C140800, // 001D CALL R5 4
0x5818000B, // 001E LDCONST R6 K11
0x7C0C0600, // 001F CALL R3 3
0x880C010C, // 0020 GETMBR R3 R0 K12
0x780E0003, // 0021 JMPF R3 #0026
0x8C0C010C, // 0022 GETMET R3 R0 K12
0x8814010D, // 0023 GETMBR R5 R0 K13
0x88180101, // 0024 GETMBR R6 R0 K1
0x7C0C0600, // 0025 CALL R3 3
0x80000000, // 0026 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_http_failed
********************************************************************/
be_local_closure(Matter_HTTP_remote_event_http_failed, /* name */
be_nested_proto(
5, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str_weak(tasmota),
/* K1 */ be_nested_str_weak(log),
/* K2 */ be_nested_str_weak(MTR_X3A_X20HTTP_X20failed),
/* K3 */ be_const_int(3),
/* K4 */ be_nested_str_weak(cb),
/* K5 */ be_nested_str_weak(http_status),
}),
be_str_weak(event_http_failed),
&be_const_str_solidified,
( &(const binstruction[12]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x8C040301, // 0001 GETMET R1 R1 K1
0x580C0002, // 0002 LDCONST R3 K2
0x58100003, // 0003 LDCONST R4 K3
0x7C040600, // 0004 CALL R1 3
0x88040104, // 0005 GETMBR R1 R0 K4
0x78060003, // 0006 JMPF R1 #000B
0x8C040104, // 0007 GETMET R1 R0 K4
0x880C0105, // 0008 GETMBR R3 R0 K5
0x4C100000, // 0009 LDNIL R4
0x7C040600, // 000A CALL R1 3
0x80000000, // 000B RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: set_cb
********************************************************************/
be_local_closure(Matter_HTTP_remote_set_cb, /* name */
be_nested_proto(
2, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_str_weak(cb),
}),
be_str_weak(set_cb),
&be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x80000000, // 0001 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: begin
********************************************************************/
be_local_closure(Matter_HTTP_remote_begin, /* name */
be_nested_proto(
11, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 9]) { /* constants */
/* K0 */ be_nested_str_weak(string),
/* K1 */ be_nested_str_weak(tasmota),
/* K2 */ be_nested_str_weak(log),
/* K3 */ be_nested_str_weak(format),
/* K4 */ be_nested_str_weak(MTR_X3A_X20HTTP_X20async_X20request_X20_X27http_X3A_X2F_X2F_X25s_X3A_X25i_X2F_X25s_X27),
/* K5 */ be_nested_str_weak(addr),
/* K6 */ be_nested_str_weak(port),
/* K7 */ be_const_int(3),
/* K8 */ be_nested_str_weak(begin),
}),
be_str_weak(begin),
&be_const_str_solidified,
( &(const binstruction[18]) { /* code */
0xA40A0000, // 0000 IMPORT R2 K0
0xB80E0200, // 0001 GETNGBL R3 K1
0x8C0C0702, // 0002 GETMET R3 R3 K2
0x8C140503, // 0003 GETMET R5 R2 K3
0x581C0004, // 0004 LDCONST R7 K4
0x88200105, // 0005 GETMBR R8 R0 K5
0x88240106, // 0006 GETMBR R9 R0 K6
0x5C280200, // 0007 MOVE R10 R1
0x7C140A00, // 0008 CALL R5 5
0x58180007, // 0009 LDCONST R6 K7
0x7C0C0600, // 000A CALL R3 3
0x600C0003, // 000B GETGBL R3 G3
0x5C100000, // 000C MOVE R4 R0
0x7C0C0200, // 000D CALL R3 1
0x8C0C0708, // 000E GETMET R3 R3 K8
0x5C140200, // 000F MOVE R5 R1
0x7C0C0400, // 0010 CALL R3 2
0x80040600, // 0011 RET 1 R3
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_http_timeout
********************************************************************/
be_local_closure(Matter_HTTP_remote_event_http_timeout, /* name */
be_nested_proto(
5, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str_weak(tasmota),
/* K1 */ be_nested_str_weak(log),
/* K2 */ be_nested_str_weak(MTR_X3A_X20HTTP_X20timeout),
/* K3 */ be_const_int(3),
/* K4 */ be_nested_str_weak(cb),
/* K5 */ be_nested_str_weak(http_status),
}),
be_str_weak(event_http_timeout),
&be_const_str_solidified,
( &(const binstruction[12]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x8C040301, // 0001 GETMET R1 R1 K1
0x580C0002, // 0002 LDCONST R3 K2
0x58100003, // 0003 LDCONST R4 K3
0x7C040600, // 0004 CALL R1 3
0x88040104, // 0005 GETMBR R1 R0 K4
0x78060003, // 0006 JMPF R1 #000B
0x8C040104, // 0007 GETMET R1 R0 K4
0x880C0105, // 0008 GETMBR R3 R0 K5
0x4C100000, // 0009 LDNIL R4
0x7C040600, // 000A CALL R1 3
0x80000000, // 000B RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: Matter_HTTP_remote
********************************************************************/
extern const bclass be_class_Matter_HTTP_async;
be_local_class(Matter_HTTP_remote,
1,
&be_class_Matter_HTTP_async,
be_nested_map(8,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_weak(cb, 1), be_const_var(0) },
{ be_const_key_weak(event_http_timeout, -1), be_const_closure(Matter_HTTP_remote_event_http_timeout_closure) },
{ be_const_key_weak(event_http_failed, -1), be_const_closure(Matter_HTTP_remote_event_http_failed_closure) },
{ be_const_key_weak(init, 7), be_const_closure(Matter_HTTP_remote_init_closure) },
{ be_const_key_weak(begin_sync, 2), be_const_closure(Matter_HTTP_remote_begin_sync_closure) },
{ be_const_key_weak(set_cb, -1), be_const_closure(Matter_HTTP_remote_set_cb_closure) },
{ be_const_key_weak(begin, -1), be_const_closure(Matter_HTTP_remote_begin_closure) },
{ be_const_key_weak(event_http_finished, -1), be_const_closure(Matter_HTTP_remote_event_http_finished_closure) },
})),
be_str_weak(Matter_HTTP_remote)
);
/*******************************************************************/
void be_load_Matter_HTTP_remote_class(bvm *vm) {
be_pushntvclass(vm, &be_class_Matter_HTTP_remote);
be_setglobal(vm, "Matter_HTTP_remote");
be_pop(vm, 1);
}
/********************************************************************/
/* End of solidification */

View File

@ -6,33 +6,6 @@
extern const bclass be_class_Matter_Plugin_Bridge_OnOff;
/********************************************************************
** Solidified function: <lambda>
********************************************************************/
be_local_closure(Matter_Plugin_Bridge_OnOff__X3Clambda_X3E, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
be_str_weak(_X3Clambda_X3E),
&be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x60040009, // 0000 GETGBL R1 G9
0x5C080000, // 0001 MOVE R2 R0
0x7C040200, // 0002 CALL R1 1
0x80040200, // 0003 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: init
********************************************************************/
@ -86,38 +59,52 @@ be_local_closure(Matter_Plugin_Bridge_OnOff_init, /* name */
/********************************************************************
** Solidified function: set_onoff
** Solidified function: parse_update
********************************************************************/
be_local_closure(Matter_Plugin_Bridge_OnOff_set_onoff, /* name */
be_local_closure(Matter_Plugin_Bridge_OnOff_parse_update, /* name */
be_nested_proto(
6, /* nstack */
2, /* argc */
8, /* nstack */
3, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
/* K0 */ be_nested_str_weak(call_remote),
/* K1 */ be_nested_str_weak(Power),
/* K2 */ be_nested_str_weak(1),
/* K3 */ be_nested_str_weak(0),
/* K4 */ be_nested_str_weak(update_shadow),
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str_weak(find),
/* K1 */ be_nested_str_weak(POWER),
/* K2 */ be_nested_str_weak(ON),
/* K3 */ be_nested_str_weak(shadow_onoff),
/* K4 */ be_nested_str_weak(attribute_updated),
/* K5 */ be_const_int(0),
}),
be_str_weak(set_onoff),
be_str_weak(parse_update),
&be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x8C080100, // 0000 GETMET R2 R0 K0
0x58100001, // 0001 LDCONST R4 K1
0x78060001, // 0002 JMPF R1 #0005
0x58140002, // 0003 LDCONST R5 K2
0x70020000, // 0004 JMP #0006
0x58140003, // 0005 LDCONST R5 K3
0x7C080600, // 0006 CALL R2 3
0x8C080104, // 0007 GETMET R2 R0 K4
0x7C080200, // 0008 CALL R2 1
0x80000000, // 0009 RET 0
( &(const binstruction[23]) { /* code */
0x540E000A, // 0000 LDINT R3 11
0x1C0C0403, // 0001 EQ R3 R2 R3
0x780E0012, // 0002 JMPF R3 #0016
0x8C0C0300, // 0003 GETMET R3 R1 K0
0x58140001, // 0004 LDCONST R5 K1
0x7C0C0400, // 0005 CALL R3 2
0x1C0C0702, // 0006 EQ R3 R3 K2
0x88100103, // 0007 GETMBR R4 R0 K3
0x4C140000, // 0008 LDNIL R5
0x20100805, // 0009 NE R4 R4 R5
0x78120009, // 000A JMPF R4 #0015
0x88100103, // 000B GETMBR R4 R0 K3
0x60140017, // 000C GETGBL R5 G23
0x5C180600, // 000D MOVE R6 R3
0x7C140200, // 000E CALL R5 1
0x20100805, // 000F NE R4 R4 R5
0x78120003, // 0010 JMPF R4 #0015
0x8C100104, // 0011 GETMET R4 R0 K4
0x541A0005, // 0012 LDINT R6 6
0x581C0005, // 0013 LDCONST R7 K5
0x7C100600, // 0014 CALL R4 3
0x90020603, // 0015 SETMBR R0 K3 R3
0x80000000, // 0016 RET 0
})
)
);
@ -201,6 +188,104 @@ be_local_closure(Matter_Plugin_Bridge_OnOff_invoke_request, /* name */
/*******************************************************************/
/********************************************************************
** Solidified function: set_onoff
********************************************************************/
be_local_closure(Matter_Plugin_Bridge_OnOff_set_onoff, /* name */
be_nested_proto(
6, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
/* K0 */ be_nested_str_weak(call_remote_sync),
/* K1 */ be_nested_str_weak(Power),
/* K2 */ be_nested_str_weak(1),
/* K3 */ be_nested_str_weak(0),
/* K4 */ be_nested_str_weak(update_shadow),
}),
be_str_weak(set_onoff),
&be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x8C080100, // 0000 GETMET R2 R0 K0
0x58100001, // 0001 LDCONST R4 K1
0x78060001, // 0002 JMPF R1 #0005
0x58140002, // 0003 LDCONST R5 K2
0x70020000, // 0004 JMP #0006
0x58140003, // 0005 LDCONST R5 K3
0x7C080600, // 0006 CALL R2 3
0x8C080104, // 0007 GETMET R2 R0 K4
0x7C080200, // 0008 CALL R2 1
0x80000000, // 0009 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: <lambda>
********************************************************************/
be_local_closure(Matter_Plugin_Bridge_OnOff__X3Clambda_X3E, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
be_str_weak(_X3Clambda_X3E),
&be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x60040009, // 0000 GETGBL R1 G9
0x5C080000, // 0001 MOVE R2 R0
0x7C040200, // 0002 CALL R1 1
0x80040200, // 0003 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: probe_shadow_async
********************************************************************/
be_local_closure(Matter_Plugin_Bridge_OnOff_probe_shadow_async, /* name */
be_nested_proto(
5, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
/* K0 */ be_nested_str_weak(call_remote_async),
/* K1 */ be_nested_str_weak(Status),
/* K2 */ be_nested_str_weak(11),
}),
be_str_weak(probe_shadow_async),
&be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x580C0001, // 0001 LDCONST R3 K1
0x58100002, // 0002 LDCONST R4 K2
0x7C040600, // 0003 CALL R1 3
0x80000000, // 0004 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: read_attribute
********************************************************************/
@ -287,7 +372,7 @@ be_local_closure(Matter_Plugin_Bridge_OnOff_read_attribute, /* name */
********************************************************************/
be_local_closure(Matter_Plugin_Bridge_OnOff_update_shadow, /* name */
be_nested_proto(
7, /* nstack */
5, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
@ -295,54 +380,25 @@ be_local_closure(Matter_Plugin_Bridge_OnOff_update_shadow, /* name */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 9]) { /* constants */
/* K0 */ be_nested_str_weak(get_status_11),
/* K1 */ be_nested_str_weak(find),
/* K2 */ be_nested_str_weak(StatusSTS),
/* K3 */ be_nested_str_weak(POWER),
/* K4 */ be_nested_str_weak(ON),
/* K5 */ be_nested_str_weak(shadow_onoff),
/* K6 */ be_nested_str_weak(attribute_updated),
/* K7 */ be_const_int(0),
/* K8 */ be_nested_str_weak(update_shadow),
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_nested_str_weak(call_remote_sync),
/* K1 */ be_nested_str_weak(Status),
/* K2 */ be_nested_str_weak(11),
/* K3 */ be_nested_str_weak(update_shadow),
}),
be_str_weak(update_shadow),
&be_const_str_solidified,
( &(const binstruction[34]) { /* code */
( &(const binstruction[10]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x7C040200, // 0001 CALL R1 1
0x78060018, // 0002 JMPF R1 #001C
0x8C080301, // 0003 GETMET R2 R1 K1
0x58100002, // 0004 LDCONST R4 K2
0x60140013, // 0005 GETGBL R5 G19
0x7C140000, // 0006 CALL R5 0
0x7C080600, // 0007 CALL R2 3
0x5C040400, // 0008 MOVE R1 R2
0x8C080301, // 0009 GETMET R2 R1 K1
0x58100003, // 000A LDCONST R4 K3
0x7C080400, // 000B CALL R2 2
0x1C080504, // 000C EQ R2 R2 K4
0x880C0105, // 000D GETMBR R3 R0 K5
0x4C100000, // 000E LDNIL R4
0x200C0604, // 000F NE R3 R3 R4
0x780E0009, // 0010 JMPF R3 #001B
0x880C0105, // 0011 GETMBR R3 R0 K5
0x60100017, // 0012 GETGBL R4 G23
0x5C140400, // 0013 MOVE R5 R2
0x7C100200, // 0014 CALL R4 1
0x200C0604, // 0015 NE R3 R3 R4
0x780E0003, // 0016 JMPF R3 #001B
0x8C0C0106, // 0017 GETMET R3 R0 K6
0x54160005, // 0018 LDINT R5 6
0x58180007, // 0019 LDCONST R6 K7
0x7C0C0600, // 001A CALL R3 3
0x90020A02, // 001B SETMBR R0 K5 R2
0x60080003, // 001C GETGBL R2 G3
0x5C0C0000, // 001D MOVE R3 R0
0x7C080200, // 001E CALL R2 1
0x8C080508, // 001F GETMET R2 R2 K8
0x7C080200, // 0020 CALL R2 1
0x80000000, // 0021 RET 0
0x580C0001, // 0001 LDCONST R3 K1
0x58100002, // 0002 LDCONST R4 K2
0x7C040600, // 0003 CALL R1 3
0x60080003, // 0004 GETGBL R2 G3
0x5C0C0000, // 0005 MOVE R3 R0
0x7C080200, // 0006 CALL R2 1
0x8C080503, // 0007 GETMET R2 R2 K3
0x7C080200, // 0008 CALL R2 1
0x80000000, // 0009 RET 0
})
)
);
@ -354,11 +410,29 @@ be_local_closure(Matter_Plugin_Bridge_OnOff_update_shadow, /* name */
********************************************************************/
extern const bclass be_class_Matter_Plugin_Bridge_HTTP;
be_local_class(Matter_Plugin_Bridge_OnOff,
3,
2,
&be_class_Matter_Plugin_Bridge_HTTP,
be_nested_map(14,
be_nested_map(15,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_weak(CLUSTERS, 11), be_const_simple_instance(be_nested_simple_instance(&be_class_map, {
{ be_const_key_weak(init, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_init_closure) },
{ be_const_key_weak(parse_update, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_parse_update_closure) },
{ be_const_key_weak(invoke_request, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_invoke_request_closure) },
{ be_const_key_weak(set_onoff, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_set_onoff_closure) },
{ be_const_key_weak(ARG_TYPE, 7), be_const_static_closure(Matter_Plugin_Bridge_OnOff__X3Clambda_X3E_closure) },
{ be_const_key_weak(tasmota_relay_index, 11), be_const_var(0) },
{ be_const_key_weak(probe_shadow_async, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_probe_shadow_async_closure) },
{ be_const_key_weak(update_shadow, 10), be_const_closure(Matter_Plugin_Bridge_OnOff_update_shadow_closure) },
{ be_const_key_weak(NAME, -1), be_nested_str_weak(_X26_X23x1F517_X3B_X20Relay) },
{ be_const_key_weak(ARG, 8), be_nested_str_weak(relay) },
{ be_const_key_weak(TYPE, 14), be_nested_str_weak(http_relay) },
{ be_const_key_weak(TYPES, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, {
be_const_map( * be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_int(266, -1), be_const_int(2) },
})) ) } )) },
{ be_const_key_weak(read_attribute, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_read_attribute_closure) },
{ be_const_key_weak(shadow_onoff, -1), be_const_var(1) },
{ be_const_key_weak(CLUSTERS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, {
be_const_map( * be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, {
@ -369,23 +443,6 @@ be_local_class(Matter_Plugin_Bridge_OnOff,
be_const_int(65533),
})) ) } )) },
})) ) } )) },
{ be_const_key_weak(ARG, -1), be_nested_str_weak(relay) },
{ be_const_key_weak(ARG_TYPE, -1), be_const_static_closure(Matter_Plugin_Bridge_OnOff__X3Clambda_X3E_closure) },
{ be_const_key_weak(TYPE, -1), be_nested_str_weak(http_relay) },
{ be_const_key_weak(update_shadow, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_update_shadow_closure) },
{ be_const_key_weak(init, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_init_closure) },
{ be_const_key_weak(shadow_onoff, 13), be_const_var(2) },
{ be_const_key_weak(invoke_request, 4), be_const_closure(Matter_Plugin_Bridge_OnOff_invoke_request_closure) },
{ be_const_key_weak(NAME, -1), be_nested_str_weak(_X26_X23x1F517_X3B_X20Relay) },
{ be_const_key_weak(tasmota_http, 12), be_const_var(0) },
{ be_const_key_weak(TYPES, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, {
be_const_map( * be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_int(266, -1), be_const_int(2) },
})) ) } )) },
{ be_const_key_weak(read_attribute, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_read_attribute_closure) },
{ be_const_key_weak(tasmota_relay_index, -1), be_const_var(1) },
{ be_const_key_weak(set_onoff, -1), be_const_closure(Matter_Plugin_Bridge_OnOff_set_onoff_closure) },
})),
be_str_weak(Matter_Plugin_Bridge_OnOff)
);

View File

@ -0,0 +1,872 @@
/* Solidification of Matter_TCP_async.h */
/********************************************************************\
* Generated code, don't edit *
\********************************************************************/
#include "be_constobj.h"
extern const bclass be_class_Matter_TCP_async;
/********************************************************************
** Solidified function: write
********************************************************************/
be_local_closure(Matter_TCP_async_write, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_nested_str_weak(tcp_connected),
/* K1 */ be_nested_str_weak(tcp),
/* K2 */ be_nested_str_weak(write),
/* K3 */ be_const_int(0),
}),
be_str_weak(write),
&be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x780A0004, // 0001 JMPF R2 #0007
0x88080101, // 0002 GETMBR R2 R0 K1
0x8C080502, // 0003 GETMET R2 R2 K2
0x5C100200, // 0004 MOVE R4 R1
0x7C080400, // 0005 CALL R2 2
0x80040400, // 0006 RET 1 R2
0x80060600, // 0007 RET 1 K3
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: readbytes
********************************************************************/
be_local_closure(Matter_TCP_async_readbytes, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
/* K0 */ be_nested_str_weak(tcp_connected),
/* K1 */ be_nested_str_weak(tcp),
/* K2 */ be_nested_str_weak(readbytes),
}),
be_str_weak(readbytes),
&be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060003, // 0001 JMPF R1 #0006
0x88040101, // 0002 GETMBR R1 R0 K1
0x8C040302, // 0003 GETMET R1 R1 K2
0x7C040200, // 0004 CALL R1 1
0x80040200, // 0005 RET 1 R1
0x4C040000, // 0006 LDNIL R1
0x80040200, // 0007 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: every_50ms
********************************************************************/
be_local_closure(Matter_TCP_async_every_50ms, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_str_weak(loop),
}),
be_str_weak(every_50ms),
&be_const_str_solidified,
( &(const binstruction[ 3]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x7C040200, // 0001 CALL R1 1
0x80000000, // 0002 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: listening
********************************************************************/
be_local_closure(Matter_TCP_async_listening, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
/* K0 */ be_nested_str_weak(tcp_connected),
/* K1 */ be_nested_str_weak(tcp),
/* K2 */ be_nested_str_weak(listening),
}),
be_str_weak(listening),
&be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060003, // 0001 JMPF R1 #0006
0x88040101, // 0002 GETMBR R1 R0 K1
0x8C040302, // 0003 GETMET R1 R1 K2
0x7C040200, // 0004 CALL R1 1
0x80040200, // 0005 RET 1 R1
0x50040000, // 0006 LDBOOL R1 0 0
0x80040200, // 0007 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: loop
********************************************************************/
be_local_closure(Matter_TCP_async_loop, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[18]) { /* constants */
/* K0 */ be_nested_str_weak(tcp_connected),
/* K1 */ be_nested_str_weak(status),
/* K2 */ be_nested_str_weak(close),
/* K3 */ be_nested_str_weak(tcp),
/* K4 */ be_nested_str_weak(connected),
/* K5 */ be_const_int(1),
/* K6 */ be_nested_str_weak(event_established),
/* K7 */ be_nested_str_weak(event_refused),
/* K8 */ be_nested_str_weak(tasmota),
/* K9 */ be_nested_str_weak(millis),
/* K10 */ be_nested_str_weak(time_start),
/* K11 */ be_nested_str_weak(timeout),
/* K12 */ be_nested_str_weak(event_timeout),
/* K13 */ be_nested_str_weak(event_closed),
/* K14 */ be_nested_str_weak(available),
/* K15 */ be_nested_str_weak(event_available),
/* K16 */ be_nested_str_weak(listening),
/* K17 */ be_nested_str_weak(event_listening),
}),
be_str_weak(loop),
&be_const_str_solidified,
( &(const binstruction[89]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x88080101, // 0001 GETMBR R2 R0 K1
0x4C0C0000, // 0002 LDNIL R3
0x1C080403, // 0003 EQ R2 R2 R3
0x780A0002, // 0004 JMPF R2 #0008
0x8C080102, // 0005 GETMET R2 R0 K2
0x7C080200, // 0006 CALL R2 1
0x80000400, // 0007 RET 0
0x88080103, // 0008 GETMBR R2 R0 K3
0x8C080504, // 0009 GETMET R2 R2 K4
0x7C080200, // 000A CALL R2 1
0x90020002, // 000B SETMBR R0 K0 R2
0x4C080000, // 000C LDNIL R2
0x1C080202, // 000D EQ R2 R1 R2
0x780A0021, // 000E JMPF R2 #0031
0x88080100, // 000F GETMBR R2 R0 K0
0x500C0200, // 0010 LDBOOL R3 1 0
0x1C080403, // 0011 EQ R2 R2 R3
0x780A0003, // 0012 JMPF R2 #0017
0x90020305, // 0013 SETMBR R0 K1 K5
0x8C080106, // 0014 GETMET R2 R0 K6
0x7C080200, // 0015 CALL R2 1
0x70020019, // 0016 JMP #0031
0x88080100, // 0017 GETMBR R2 R0 K0
0x500C0000, // 0018 LDBOOL R3 0 0
0x1C080403, // 0019 EQ R2 R2 R3
0x780A0007, // 001A JMPF R2 #0023
0x5409FFFD, // 001B LDINT R2 -2
0x90020202, // 001C SETMBR R0 K1 R2
0x8C080107, // 001D GETMET R2 R0 K7
0x7C080200, // 001E CALL R2 1
0x8C080102, // 001F GETMET R2 R0 K2
0x7C080200, // 0020 CALL R2 1
0x80000400, // 0021 RET 0
0x7002000D, // 0022 JMP #0031
0xB80A1000, // 0023 GETNGBL R2 K8
0x8C080509, // 0024 GETMET R2 R2 K9
0x7C080200, // 0025 CALL R2 1
0x880C010A, // 0026 GETMBR R3 R0 K10
0x04080403, // 0027 SUB R2 R2 R3
0x880C010B, // 0028 GETMBR R3 R0 K11
0x24080403, // 0029 GT R2 R2 R3
0x780A0005, // 002A JMPF R2 #0031
0x5409FFFC, // 002B LDINT R2 -3
0x90020202, // 002C SETMBR R0 K1 R2
0x50080000, // 002D LDBOOL R2 0 0
0x90020002, // 002E SETMBR R0 K0 R2
0x8C08010C, // 002F GETMET R2 R0 K12
0x7C080200, // 0030 CALL R2 1
0xB80A1000, // 0031 GETNGBL R2 K8
0x8C080509, // 0032 GETMET R2 R2 K9
0x7C080200, // 0033 CALL R2 1
0x880C010A, // 0034 GETMBR R3 R0 K10
0x04080403, // 0035 SUB R2 R2 R3
0x880C010B, // 0036 GETMBR R3 R0 K11
0x24080403, // 0037 GT R2 R2 R3
0x780A0006, // 0038 JMPF R2 #0040
0x8C080102, // 0039 GETMET R2 R0 K2
0x7C080200, // 003A CALL R2 1
0x5409FFFC, // 003B LDINT R2 -3
0x90020202, // 003C SETMBR R0 K1 R2
0x8C08010C, // 003D GETMET R2 R0 K12
0x7C080200, // 003E CALL R2 1
0x80000400, // 003F RET 0
0x88080100, // 0040 GETMBR R2 R0 K0
0x500C0000, // 0041 LDBOOL R3 0 0
0x1C080403, // 0042 EQ R2 R2 R3
0x780A0007, // 0043 JMPF R2 #004C
0x50080200, // 0044 LDBOOL R2 1 0
0x1C080202, // 0045 EQ R2 R1 R2
0x780A0001, // 0046 JMPF R2 #0049
0x8C08010D, // 0047 GETMET R2 R0 K13
0x7C080200, // 0048 CALL R2 1
0x8C080102, // 0049 GETMET R2 R0 K2
0x7C080200, // 004A CALL R2 1
0x80000400, // 004B RET 0
0x88080103, // 004C GETMBR R2 R0 K3
0x8C08050E, // 004D GETMET R2 R2 K14
0x7C080200, // 004E CALL R2 1
0x780A0001, // 004F JMPF R2 #0052
0x8C08010F, // 0050 GETMET R2 R0 K15
0x7C080200, // 0051 CALL R2 1
0x88080103, // 0052 GETMBR R2 R0 K3
0x8C080510, // 0053 GETMET R2 R2 K16
0x7C080200, // 0054 CALL R2 1
0x780A0001, // 0055 JMPF R2 #0058
0x8C080111, // 0056 GETMET R2 R0 K17
0x7C080200, // 0057 CALL R2 1
0x80000000, // 0058 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_established
********************************************************************/
be_local_closure(Matter_TCP_async_event_established, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
be_str_weak(event_established),
&be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: reset
********************************************************************/
be_local_closure(Matter_TCP_async_reset, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
/* K0 */ be_nested_str_weak(tcp),
/* K1 */ be_nested_str_weak(close),
/* K2 */ be_nested_str_weak(tcp_connected),
}),
be_str_weak(reset),
&be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
0x7C040200, // 0002 CALL R1 1
0x4C040000, // 0003 LDNIL R1
0x90020401, // 0004 SETMBR R0 K2 R1
0x80000000, // 0005 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_listening
********************************************************************/
be_local_closure(Matter_TCP_async_event_listening, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
be_str_weak(event_listening),
&be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(Matter_TCP_async_init, /* name */
be_nested_proto(
7, /* nstack */
5, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
1, /* has sup protos */
( &(const struct bproto*[ 1]) {
be_nested_proto(
2, /* nstack */
0, /* argc */
0, /* varg */
1, /* has upvals */
( &(const bupvaldesc[ 1]) { /* upvals */
be_local_const_upval(1, 0),
}),
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_str_weak(loop),
}),
be_str_weak(_X3Clambda_X3E),
&be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
0x68000000, // 0000 GETUPV R0 U0
0x8C000100, // 0001 GETMET R0 R0 K0
0x7C000200, // 0002 CALL R0 1
0x80040000, // 0003 RET 1 R0
})
),
}),
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
/* K0 */ be_nested_str_weak(TIMEOUT),
/* K1 */ be_nested_str_weak(addr),
/* K2 */ be_nested_str_weak(port),
/* K3 */ be_nested_str_weak(timeout),
/* K4 */ be_nested_str_weak(tcp),
/* K5 */ be_nested_str_weak(tcpclientasync),
/* K6 */ be_nested_str_weak(fast_loop),
}),
be_str_weak(init),
&be_const_str_solidified,
( &(const binstruction[25]) { /* code */
0x4C140000, // 0000 LDNIL R5
0x1C140605, // 0001 EQ R5 R3 R5
0x78160000, // 0002 JMPF R5 #0004
0x880C0100, // 0003 GETMBR R3 R0 K0
0x4C140000, // 0004 LDNIL R5
0x1C140405, // 0005 EQ R5 R2 R5
0x78160000, // 0006 JMPF R5 #0008
0x540A004F, // 0007 LDINT R2 80
0x60140008, // 0008 GETGBL R5 G8
0x5C180200, // 0009 MOVE R6 R1
0x7C140200, // 000A CALL R5 1
0x90020205, // 000B SETMBR R0 K1 R5
0x60140009, // 000C GETGBL R5 G9
0x5C180400, // 000D MOVE R6 R2
0x7C140200, // 000E CALL R5 1
0x90020405, // 000F SETMBR R0 K2 R5
0x90020603, // 0010 SETMBR R0 K3 R3
0xB8160A00, // 0011 GETNGBL R5 K5
0x7C140000, // 0012 CALL R5 0
0x90020805, // 0013 SETMBR R0 K4 R5
0x78120001, // 0014 JMPF R4 #0017
0x84140000, // 0015 CLOSURE R5 P0
0x90020C05, // 0016 SETMBR R0 K6 R5
0xA0000000, // 0017 CLOSE R0
0x80000000, // 0018 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_closed
********************************************************************/
be_local_closure(Matter_TCP_async_event_closed, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
be_str_weak(event_closed),
&be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: read
********************************************************************/
be_local_closure(Matter_TCP_async_read, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
/* K0 */ be_nested_str_weak(tcp_connected),
/* K1 */ be_nested_str_weak(tcp),
/* K2 */ be_nested_str_weak(read),
}),
be_str_weak(read),
&be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060003, // 0001 JMPF R1 #0006
0x88040101, // 0002 GETMBR R1 R0 K1
0x8C040302, // 0003 GETMET R1 R1 K2
0x7C040200, // 0004 CALL R1 1
0x80040200, // 0005 RET 1 R1
0x4C040000, // 0006 LDNIL R1
0x80040200, // 0007 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: begin
********************************************************************/
be_local_closure(Matter_TCP_async_begin, /* name */
be_nested_proto(
9, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[25]) { /* constants */
/* K0 */ be_nested_str_weak(reset),
/* K1 */ be_nested_str_weak(tasmota),
/* K2 */ be_nested_str_weak(wifi),
/* K3 */ be_nested_str_weak(up),
/* K4 */ be_nested_str_weak(eth),
/* K5 */ be_nested_str_weak(time_start),
/* K6 */ be_nested_str_weak(millis),
/* K7 */ be_nested_str_weak(status),
/* K8 */ be_const_int(0),
/* K9 */ be_nested_str_weak(tcp),
/* K10 */ be_nested_str_weak(connect),
/* K11 */ be_nested_str_weak(addr),
/* K12 */ be_nested_str_weak(port),
/* K13 */ be_nested_str_weak(fast_loop),
/* K14 */ be_nested_str_weak(remove_fast_loop),
/* K15 */ be_nested_str_weak(add_fast_loop),
/* K16 */ be_nested_str_weak(add_driver),
/* K17 */ be_nested_str_weak(string),
/* K18 */ be_nested_str_weak(log),
/* K19 */ be_nested_str_weak(format),
/* K20 */ be_nested_str_weak(BRY_X3A_X20failed_X20to_X20resolve_X20_X5B_X25s_X5D_X3A_X25i),
/* K21 */ be_const_int(3),
/* K22 */ be_nested_str_weak(close),
/* K23 */ be_nested_str_weak(tcp_connected),
/* K24 */ be_nested_str_weak(event_dnsfailed),
}),
be_str_weak(begin),
&be_const_str_solidified,
( &(const binstruction[64]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x7C040200, // 0001 CALL R1 1
0xB8060200, // 0002 GETNGBL R1 K1
0x8C040302, // 0003 GETMET R1 R1 K2
0x7C040200, // 0004 CALL R1 1
0x94040303, // 0005 GETIDX R1 R1 K3
0x74060006, // 0006 JMPT R1 #000E
0xB8060200, // 0007 GETNGBL R1 K1
0x8C040304, // 0008 GETMET R1 R1 K4
0x7C040200, // 0009 CALL R1 1
0x94040303, // 000A GETIDX R1 R1 K3
0x74060001, // 000B JMPT R1 #000E
0x4C040000, // 000C LDNIL R1
0x80040200, // 000D RET 1 R1
0xB8060200, // 000E GETNGBL R1 K1
0x8C040306, // 000F GETMET R1 R1 K6
0x7C040200, // 0010 CALL R1 1
0x90020A01, // 0011 SETMBR R0 K5 R1
0x90020F08, // 0012 SETMBR R0 K7 K8
0x88040109, // 0013 GETMBR R1 R0 K9
0x8C04030A, // 0014 GETMET R1 R1 K10
0x880C010B, // 0015 GETMBR R3 R0 K11
0x8810010C, // 0016 GETMBR R4 R0 K12
0x7C040600, // 0017 CALL R1 3
0x78060011, // 0018 JMPF R1 #002B
0x8804010D, // 0019 GETMBR R1 R0 K13
0x78060008, // 001A JMPF R1 #0024
0xB8060200, // 001B GETNGBL R1 K1
0x8C04030E, // 001C GETMET R1 R1 K14
0x880C010D, // 001D GETMBR R3 R0 K13
0x7C040400, // 001E CALL R1 2
0xB8060200, // 001F GETNGBL R1 K1
0x8C04030F, // 0020 GETMET R1 R1 K15
0x880C010D, // 0021 GETMBR R3 R0 K13
0x7C040400, // 0022 CALL R1 2
0x70020003, // 0023 JMP #0028
0xB8060200, // 0024 GETNGBL R1 K1
0x8C040310, // 0025 GETMET R1 R1 K16
0x5C0C0000, // 0026 MOVE R3 R0
0x7C040400, // 0027 CALL R1 2
0x50040200, // 0028 LDBOOL R1 1 0
0x80040200, // 0029 RET 1 R1
0x70020013, // 002A JMP #003F
0xA4062200, // 002B IMPORT R1 K17
0xB80A0200, // 002C GETNGBL R2 K1
0x8C080512, // 002D GETMET R2 R2 K18
0x8C100313, // 002E GETMET R4 R1 K19
0x58180014, // 002F LDCONST R6 K20
0x881C010B, // 0030 GETMBR R7 R0 K11
0x8820010C, // 0031 GETMBR R8 R0 K12
0x7C100800, // 0032 CALL R4 4
0x58140015, // 0033 LDCONST R5 K21
0x7C080600, // 0034 CALL R2 3
0x8C080116, // 0035 GETMET R2 R0 K22
0x7C080200, // 0036 CALL R2 1
0x5409FFFE, // 0037 LDINT R2 -1
0x90020E02, // 0038 SETMBR R0 K7 R2
0x50080000, // 0039 LDBOOL R2 0 0
0x90022E02, // 003A SETMBR R0 K23 R2
0x8C080118, // 003B GETMET R2 R0 K24
0x7C080200, // 003C CALL R2 1
0x50080000, // 003D LDBOOL R2 0 0
0x80040400, // 003E RET 1 R2
0x80000000, // 003F RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_timeout
********************************************************************/
be_local_closure(Matter_TCP_async_event_timeout, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
be_str_weak(event_timeout),
&be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: available
********************************************************************/
be_local_closure(Matter_TCP_async_available, /* name */
be_nested_proto(
3, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_nested_str_weak(tcp_connected),
/* K1 */ be_nested_str_weak(tcp),
/* K2 */ be_nested_str_weak(available),
/* K3 */ be_const_int(0),
}),
be_str_weak(available),
&be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060003, // 0001 JMPF R1 #0006
0x88040101, // 0002 GETMBR R1 R0 K1
0x8C040302, // 0003 GETMET R1 R1 K2
0x7C040200, // 0004 CALL R1 1
0x80040200, // 0005 RET 1 R1
0x80060600, // 0006 RET 1 K3
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_refused
********************************************************************/
be_local_closure(Matter_TCP_async_event_refused, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
be_str_weak(event_refused),
&be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_dnsfailed
********************************************************************/
be_local_closure(Matter_TCP_async_event_dnsfailed, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
be_str_weak(event_dnsfailed),
&be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: event_available
********************************************************************/
be_local_closure(Matter_TCP_async_event_available, /* name */
be_nested_proto(
1, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
0, /* has constants */
NULL, /* no const */
be_str_weak(event_available),
&be_const_str_solidified,
( &(const binstruction[ 1]) { /* code */
0x80000000, // 0000 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: close
********************************************************************/
be_local_closure(Matter_TCP_async_close, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 8]) { /* constants */
/* K0 */ be_nested_str_weak(tcp),
/* K1 */ be_nested_str_weak(close),
/* K2 */ be_nested_str_weak(fast_loop),
/* K3 */ be_nested_str_weak(tasmota),
/* K4 */ be_nested_str_weak(remove_fast_loop),
/* K5 */ be_nested_str_weak(remove_driver),
/* K6 */ be_nested_str_weak(tcp_connected),
/* K7 */ be_nested_str_weak(event_closed),
}),
be_str_weak(close),
&be_const_str_solidified,
( &(const binstruction[23]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x8C040301, // 0001 GETMET R1 R1 K1
0x7C040200, // 0002 CALL R1 1
0x88040102, // 0003 GETMBR R1 R0 K2
0x78060004, // 0004 JMPF R1 #000A
0xB8060600, // 0005 GETNGBL R1 K3
0x8C040304, // 0006 GETMET R1 R1 K4
0x880C0102, // 0007 GETMBR R3 R0 K2
0x7C040400, // 0008 CALL R1 2
0x70020003, // 0009 JMP #000E
0xB8060600, // 000A GETNGBL R1 K3
0x8C040305, // 000B GETMET R1 R1 K5
0x5C0C0000, // 000C MOVE R3 R0
0x7C040400, // 000D CALL R1 2
0x88040106, // 000E GETMBR R1 R0 K6
0x50080200, // 000F LDBOOL R2 1 0
0x1C040202, // 0010 EQ R1 R1 R2
0x78060001, // 0011 JMPF R1 #0014
0x8C040107, // 0012 GETMET R1 R0 K7
0x7C040200, // 0013 CALL R1 1
0x50040000, // 0014 LDBOOL R1 0 0
0x90020C01, // 0015 SETMBR R0 K6 R1
0x80000000, // 0016 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: set_timeout
********************************************************************/
be_local_closure(Matter_TCP_async_set_timeout, /* name */
be_nested_proto(
3, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_str_weak(TIMEOUT),
/* K1 */ be_nested_str_weak(timeout),
}),
be_str_weak(set_timeout),
&be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x4C080000, // 0000 LDNIL R2
0x1C080202, // 0001 EQ R2 R1 R2
0x780A0000, // 0002 JMPF R2 #0004
0x88040100, // 0003 GETMBR R1 R0 K0
0x90020201, // 0004 SETMBR R0 K1 R1
0x80000000, // 0005 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: Matter_TCP_async
********************************************************************/
be_local_class(Matter_TCP_async,
8,
NULL,
be_nested_map(28,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_weak(write, -1), be_const_closure(Matter_TCP_async_write_closure) },
{ be_const_key_weak(timeout, -1), be_const_var(2) },
{ be_const_key_weak(port, -1), be_const_var(1) },
{ be_const_key_weak(close, 7), be_const_closure(Matter_TCP_async_close_closure) },
{ be_const_key_weak(tcp, -1), be_const_var(3) },
{ be_const_key_weak(tcp_connected, -1), be_const_var(5) },
{ be_const_key_weak(listening, -1), be_const_closure(Matter_TCP_async_listening_closure) },
{ be_const_key_weak(event_available, -1), be_const_closure(Matter_TCP_async_event_available_closure) },
{ be_const_key_weak(readbytes, 1), be_const_closure(Matter_TCP_async_readbytes_closure) },
{ be_const_key_weak(event_dnsfailed, -1), be_const_closure(Matter_TCP_async_event_dnsfailed_closure) },
{ be_const_key_weak(event_established, -1), be_const_closure(Matter_TCP_async_event_established_closure) },
{ be_const_key_weak(event_refused, 21), be_const_closure(Matter_TCP_async_event_refused_closure) },
{ be_const_key_weak(reset, -1), be_const_closure(Matter_TCP_async_reset_closure) },
{ be_const_key_weak(event_listening, -1), be_const_closure(Matter_TCP_async_event_listening_closure) },
{ be_const_key_weak(event_timeout, -1), be_const_closure(Matter_TCP_async_event_timeout_closure) },
{ be_const_key_weak(status, 25), be_const_var(6) },
{ be_const_key_weak(every_50ms, 11), be_const_closure(Matter_TCP_async_every_50ms_closure) },
{ be_const_key_weak(read, -1), be_const_closure(Matter_TCP_async_read_closure) },
{ be_const_key_weak(begin, -1), be_const_closure(Matter_TCP_async_begin_closure) },
{ be_const_key_weak(init, 14), be_const_closure(Matter_TCP_async_init_closure) },
{ be_const_key_weak(available, -1), be_const_closure(Matter_TCP_async_available_closure) },
{ be_const_key_weak(event_closed, -1), be_const_closure(Matter_TCP_async_event_closed_closure) },
{ be_const_key_weak(addr, 9), be_const_var(0) },
{ be_const_key_weak(loop, 3), be_const_closure(Matter_TCP_async_loop_closure) },
{ be_const_key_weak(TIMEOUT, 5), be_const_int(1000) },
{ be_const_key_weak(time_start, -1), be_const_var(4) },
{ be_const_key_weak(fast_loop, 2), be_const_var(7) },
{ be_const_key_weak(set_timeout, -1), be_const_closure(Matter_TCP_async_set_timeout_closure) },
})),
be_str_weak(Matter_TCP_async)
);
/*******************************************************************/
void be_load_Matter_TCP_async_class(bvm *vm) {
be_pushntvclass(vm, &be_class_Matter_TCP_async);
be_setglobal(vm, "Matter_TCP_async");
be_pop(vm, 1);
}
/********************************************************************/
/* End of solidification */