def step_no_periodic(self): calvinsys.read(self.timer) # Ack if self.count == self.start + 2: # now continue with periodic timer events calvinsys.close(self.timer) self.timer = calvinsys.open(self, 'sys.timer.repeating') calvinsys.can_write(self.timer) # Dummy read calvinsys.write(self.timer, self.sleep) self.count += 1 return (self.count - 1, )
def step_no_periodic(self): calvinsys.read(self.timer) # Ack if self.count == self.start + 2: # now continue with periodic timer events calvinsys.close(self.timer) self.timer = calvinsys.open(self, 'sys.timer.repeating') calvinsys.can_write(self.timer) # Dummy read calvinsys.write(self.timer, self.sleep) self.count += 1 return (self.count - 1, )
class ServoMotor(Actor): """ Rotate servo given degrees. Input: angle : set servo to given angle """ @manage([]) def init(self): self.setup() def setup(self): self._servo = calvinsys.open(self, "io.servomotor") calvinsys.write(self._servo, 90) @stateguard(lambda self: calvinsys.can_write(self._servo)) @condition(action_input=("angle",)) def set_angle(self, angle): calvinsys.write(self._servo, angle) action_priority = (set_angle, ) requires = ["io.servomotor"] test_calvinsys = {'io.servomotor': {'write': [90, -90, 90, 180, -45]}} test_set = [ { 'inports': {'angle': [-90, 90, 180, -45]}, } ]
class Light(Actor): """ Set state of a light (e.g. an LED or a lightbulb) Input: on : true if light should be on, false if turned off """ def init(self): self.light = None self.setup() def setup(self): self.light = calvinsys.open(self, "io.light") def will_migrate(self): calvinsys.close(self.light) self.light = None def will_end(self): if self.light: calvinsys.close(self.light) def did_migrate(self): self.setup() @stateguard(lambda self: self.light and calvinsys.can_write(self.light)) @condition(action_input=("on", )) def set_state(self, state): calvinsys.write(self.light, 1 if state else 0) action_priority = (set_state, ) requires = ["io.light"]
class SimpleUDPSender(Actor): """ Send all incoming tokens to given address/port over UDP Input: data : Each received token will be sent to address set via control port """ @manage(['address', 'port']) def init(self, address, port): self.address = address self.port = port self.sender = None self.setup() def did_migrate(self): self.setup() def setup(self): self.sender = calvinsys.open(self, "network.socketclient", address=self.address, port=self.port, connection_type="UDP") @stateguard(lambda self: self.sender and calvinsys.can_write(self.sender)) @condition(action_input=['data']) def send(self, token): calvinsys.write(self.sender, token) action_priority = (send, ) requires = ['network.socketclient']
class Twitter(Actor): """ Post incoming tokens (text) as twitter status Input: status : A text (with a maximum length) """ @manage([]) def init(self): self.setup() def did_migrate(self): self.setup() def setup(self): self._twit = calvinsys.open(self, "web.twitter.post") def teardown(self): calvinsys.close(self._twit) def will_migrate(self): self.teardown() def will_end(self): self.teardown() @stateguard(lambda self: self._twit and calvinsys.can_write(self._twit)) @condition(action_input=['status']) def post_update(self, status): calvinsys.write(self._twit, status) action_priority = (post_update,) requires = ['web.twitter.post']
class TriggeredTemperature(Actor): """ Measure temperature. Inputs: trigger : any token triggers meausurement Outputs: centigrade : temperature, in centigrade """ @manage(['temperature']) def init(self): self.temperature = calvinsys.open(self, "io.temperature") @stateguard(lambda self: calvinsys.can_read(self.temperature)) @condition([], ['centigrade']) def read_measurement(self): data = calvinsys.read(self.temperature) return (data, ) @stateguard(lambda self: calvinsys.can_write(self.temperature)) @condition(['trigger'], []) def trigger_measurement(self, _): calvinsys.write(self.temperature, True) action_priority = (read_measurement, trigger_measurement) requires = ['io.temperature']
class Print(Actor): """ Print data to standard out of runtime. Note that what constitutes standard out varies. Input: token : data to write """ def exception_handler(self, action, args): # Check args to verify that it is EOSToken return action(self, *args) @manage(include=['stdout']) def init(self): self.stdout = calvinsys.open(self, "io.stdout") @stateguard(lambda self: calvinsys.can_write(self.stdout)) @condition(action_input=['token']) def write(self, data): calvinsys.write(self.stdout, data) action_priority = (write, ) requires = ['io.stdout'] test_calvinsys = {'io.stdout': {'write': ["This", "is", "a", "print"]}} test_set = [{ 'inports': { 'token': ["This", "is", "a", "print"] }, }]
class Buzzer(Actor): """ Buzz Input: on : true/false for on/off """ @manage([]) def init(self): self.setup() def setup(self): self.buzzer = calvinsys.open(self, "io.buzzer") def will_end(self): if self.buzzer: calvinsys.close(self.buzzer) def did_migrate(self): self.setup() @stateguard(lambda actor: calvinsys.can_write(actor.buzzer)) @condition(["on"], []) def turn_on_off(self, on): calvinsys.write(self.buzzer, bool(on)) action_priority = (turn_on_off, ) requires = ["io.buzzer"] test_calvinsys = {'io.buzzer': {'write': [True, False, True, False]}} test_set = [{ 'inports': { 'on': [True, False, True, False] }, }]
class NexaSwitch(Actor): """ Control a wireless power outlet Inputs: state : 1/0 for on/off """ @manage(['databits', 'tx']) def init(self, tx_id, group_cmd, channel, unit): self.databits = (tx_id & 0x03FFFFFF) << 6 self.databits |= ((group_cmd & 0x1) << 5) self.databits |= ((channel & 0x3) << 2) self.databits |= (unit & 0x3) self.databits &= 0xFFFFFFEF self.tx = calvinsys.open(self, "io.tx433MHz") @stateguard(lambda self: calvinsys.can_write(self.tx)) @condition(action_input=["state"]) def switch_state(self, state): data = self.databits data |= ((int(not state) & 0x1) << 4) wf = Waveform() calvinsys.write(self.tx, wf.sequence(data)) action_priority = (switch_state, ) requires = ["io.tx433MHz"]
class LogInfo(Actor): """ Write data to system log at loglevel "INFO" Input: data : data to be logged """ def exception_handler(self, action_function, args): # The action 'log' takes a single token exception_token = args[0] return action_function(self, "Exception '%s'" % (exception_token, )) @manage(["log"]) def init(self): self.log = calvinsys.open(self, "log.info") @stateguard(lambda self: calvinsys.can_write(self.log)) @condition(action_input=['data']) def write(self, data): calvinsys.write(self.log, data) action_priority = (write, ) requires = ["log.info"] test_calvinsys = {'log.info': {'write': ['a', 'b', 'c', 'd']}} test_set = [{ 'inports': { 'data': ['a', 'b', 'c', 'd'] }, }]
class Pushbullet(Actor): """ Post incoming tokens (text) to runtime specific pushbullet channel with given title Input: message : A message """ @manage(["title"]) def init(self, title): self._title = title self.setup() def did_migrate(self): self.setup() def setup(self): self._pb = calvinsys.open(self, "web.pushbullet.channel.post") def teardown(self): calvinsys.close(self._pb) def will_migrate(self): self.teardown() def will_end(self): self.teardown() @stateguard(lambda self: self._pb and calvinsys.can_write(self._pb)) @condition(action_input=['message']) def post_update(self, message): calvinsys.write(self._pb, {"message": message, "title": self._title}) action_priority = (post_update, ) requires = ['web.pushbullet.channel.post']
class TriggeredSoilMoisture(Actor): """ Measure the moisture level in the soil. Inputs: trigger : any token triggers meausurement Outputs: level : moisture level, in percent """ @manage(exclude=['level']) def init(self): self.setup() def setup(self): self.level = calvinsys.open(self, "io.soilmoisture") def teardown(self): calvinsys.close(self.level) def will_migrate(self): self.teardown() def did_migrate(self): self.setup() def will_end(self): self.teardown() @stateguard(lambda self: calvinsys.can_write(self.level)) @condition(['trigger'], []) def trigger_measurement(self, _): calvinsys.write(self.level, True) @stateguard(lambda self: calvinsys.can_read(self.level)) @condition([], ['level']) def read_measurement(self): level = calvinsys.read(self.level) return (level, ) action_priority = (read_measurement, trigger_measurement) requires = ['io.soilmoisture'] test_calvinsys = { 'io.soilmoisture': { 'read': [50, 40], 'write': [True, True] } } test_set = [{ 'inports': { 'trigger': [True, "True"] }, 'outports': { 'level': [50, 40] } }]
class LocationWeather(Actor): """ Get current weather at selected destination, given as "city,country code", "city", or ",country code" Input: location : location to fetch weather from Output: forecast: weather at given city, or null on error """ @manage([]) def init(self): self.setup() def did_migrate(self): self.setup() def setup(self): self._service = calvinsys.open(self, "weather") def teardown(self): calvinsys.close(self._service) def will_migrate(self): self.teardown() def will_end(self): self.teardown() @stateguard( lambda self: self._service and calvinsys.can_write(self._service)) @condition(action_input=['location']) def start_forecast(self, location): calvinsys.write(self._service, location) @stateguard( lambda self: self._service and calvinsys.can_read(self._service)) @condition(action_output=['forecast']) def finish_forecast(self): forecast = calvinsys.read(self._service) return (forecast, ) action_priority = ( start_forecast, finish_forecast, ) requires = ['weather'] test_calvinsys = {'weather': {'read': ["sunny"], 'write': ["Lund"]}} test_set = [{ 'inports': { 'location': ["Lund"] }, 'outports': { 'forecast': ["sunny"] } }]
class HTTPPut(Actor): """ Post data to URL Input: URL : URL to put to data : Data to put params : dictionary with query parameters (optional) headers: dictionary with headers to include in request (optional) auth : dictionary with authtype (basic/digest), username and password (optional) Output: status: HTTP status of request headers: dictionary of response headers data : body of response (only if body is non-empty) """ @manage() def init(self): self.cmd = calvinsys.open(self, "http.put") self.response = None @stateguard(lambda actor: calvinsys.can_write(actor.cmd)) @condition(action_input=['URL', 'data', 'params', 'headers', 'auth']) def new_request(self, url, data, params, headers, auth): calvinsys.write( self.cmd, { "url": url, "data": data, "params": params, "headers": headers, "auth": auth }) @stateguard(lambda actor: calvinsys.can_read(actor.cmd)) @condition() def handle_reply(self): self.response = calvinsys.read(self.cmd) @stateguard(lambda actor: actor.response and actor.response.get("body")) @condition(action_output=['status', 'headers', 'data']) def reply_with_body(self): response = self.response self.response = None return (response.get("status"), response.get("headers"), response.get("body")) @stateguard(lambda actor: actor.response and not actor.response.get("body") ) @condition(action_output=['status', 'headers']) def reply_without_body(self): response = self.response self.response = None return (response.get("status"), response.get("headers")) action_priority = (new_request, handle_reply, reply_with_body, reply_without_body) requires = ['http.put']
class TriggeredDistance(Actor): """ Measure distance. Inputs: trigger : any token triggers meausurement Outputs: meters : distance, in meters """ @manage([]) def init(self): self.setup() def setup(self): self._distance = calvinsys.open(self, "io.distance") def teardown(self): if self._distance: calvinsys.close(self._distance) self._distance = None def will_migrate(self): self.teardown() def did_migrate(self): self.setup() def will_end(self): self.teardown() @stateguard(lambda self: calvinsys.can_read(self._distance)) @condition([], ['meters']) def read_measurement(self): distance = calvinsys.read(self._distance) return (distance, ) @stateguard(lambda self: calvinsys.can_write(self._distance)) @condition(['trigger'], []) def trigger_measurement(self, _): calvinsys.write(self._distance, True) action_priority = (read_measurement, trigger_measurement) requires = ['io.distance'] test_calvinsys = {'io.distance': {'read': [10, 12, 0, 5], 'write': [True]}} test_set = [{ 'inports': { 'trigger': [True] }, 'outports': { 'meters': [10, 12, 0, 5] } }]
def set_dutycycle(self, dutycycle): try: dc = int(dutycycle) if dc < 0: dc = 0 if dc > 100: dc = 100 self.dutycycle = dc except Exception: self.dutycycle = 0 if calvinsys.can_write(self.pwm): calvinsys.write(self.pwm, self.dutycycle)
def set_volume(self, volume): try: vol = int(volume) if vol < 0: vol = 0 if vol > 100: vol = 100 self.volume = vol except Exception: self.volume = 0 if calvinsys.can_write(self.buzzer): calvinsys.write(self.buzzer, self.volume)
def set_dutycycle(self, dutycycle): try: dc = int(dutycycle) if dc < 0: dc = 0 if dc > 100: dc = 100 self.dutycycle = dc except Exception: self.dutycycle = 0 if calvinsys.can_write(self.pwm): calvinsys.write(self.pwm, self.dutycycle)
class LocalWeather(Actor): """ Get current weather where runtime is located (or think it is located) Input: trigger : start fetching weather on any token Output: forecast: weather at preconfigured city, or null on error """ @manage([]) def init(self): self.setup() def did_migrate(self): self.setup() def setup(self): self._service = calvinsys.open(self, "weather.local") calvinsys.write(self._service, None) def teardown(self): calvinsys.close(self._service) def will_migrate(self): self.teardown() def will_end(self): self.teardown() @stateguard(lambda self: self._service and calvinsys.can_write(self._service)) @condition(action_input=['trigger']) def start_forecast(self, _): calvinsys.write(self._service, None) @stateguard(lambda self: self._service and calvinsys.can_read(self._service)) @condition(action_output=['forecast']) def finish_forecast(self): forecast = calvinsys.read(self._service) return (forecast,) action_priority = (start_forecast, finish_forecast,) requires = ['weather.local'] test_calvinsys = {'weather.local': {'read': ["sunny"], 'write': [None, None]}} test_set = [ { 'inports': {'trigger': [True]}, 'outports': {'forecast': ["sunny"]} } ]
class FileWriter(Actor): """ Writes input 'data' to file 'basename' + some counter + '.' + suffix End of stream token changes file inputs: data: data """ @manage(['basename', 'counter', 'suffix']) def init(self, basename, suffix=""): self.basename = basename self.suffix = suffix self.counter = 0 self.file = None self.setup() def setup(self): fname = new_filename(self.basename, self.counter, self.suffix) self.counter += 1 self.file = calvinsys.open(self, "io.filewriter", filename=fname, mode="w") def did_migrate(self): self.file = None self.setup() def will_end(self): if self.file is not None: calvinsys.close(self.file) self.file = None @stateguard(lambda self: self.file and calvinsys.can_write(self.file)) @condition(action_input=['data']) def writef(self, data): calvinsys.write(self.file, data.encode('utf-8')) action_priority = (writef, ) requires = ['io.filewriter'] test_kwargs = {'basename': 'test'} test_calvinsys = { 'io.filewriter': { 'write': ['the quick brown fox jumped over the lazy dog'] }, } test_set = [{ 'inports': { 'data': ['the quick brown fox jumped over the lazy dog'] } }]
class Distance(Actor): """ Measure distance. Takes the frequency of measurements, in Hz, as input. Outputs: meters : distance, in meters """ @manage(['frequency']) def init(self, frequency): self.frequency = frequency self.setup() def setup(self): _log.info("setup") self._distance = calvinsys.open(self, "io.distance") self._timer = calvinsys.open(self, "sys.timer.repeating") calvinsys.write(self._timer, 1.0/self.frequency) def will_migrate(self): calvinsys.close(self._distance) calvinsys.close(self._timer) self._distance = None self._timer = None def did_migrate(self): self.setup() def will_end(self): if self._distance: calvinsys.close(self._distance) if self._timer : calvinsys.close(self._timer) @stateguard(lambda self: calvinsys.can_read(self._distance)) @condition([], ['meters']) def read_measurement(self): distance = calvinsys.read(self._distance) return (distance,) @stateguard(lambda self: calvinsys.can_read(self._timer) and calvinsys.can_write(self._distance)) @condition([], []) def start_measurement(self): calvinsys.read(self._timer) calvinsys.write(self._distance, True) action_priority = (read_measurement, start_measurement) requires = ['io.distance', 'sys.timer.repeating']
class TriggeredRelativeHumidity(Actor): """ Read Relative Humidity when told to. Inputs: measure: Triggers a temperature reading Outputs: percent: The measured humidity in percent """ @manage([]) def init(self): self.relhum = None self.setup() def setup(self): self.relhum = calvinsys.open(self, 'io.humidity') def did_migrate(self): self.setup() def will_end(self): calvinsys.close(self.relhum) @stateguard(lambda self: calvinsys.can_write(self.relhum)) @condition(['measure'], []) def measure(self, _): calvinsys.write(self.relhum, True) @stateguard(lambda self: calvinsys.can_read(self.relhum)) @condition([], ['percent']) def deliver(self): humidity = calvinsys.read(self.relhum) return (humidity, ) action_priority = ( deliver, measure, ) requires = ['io.humidity'] test_calvinsys = {'io.humidity': {'read': [50, 40], 'write': [True, True]}} test_set = [{ 'inports': { 'measure': [True, "True"] }, 'outports': { 'percent': [50, 40] } }]
class FaceFinder(Actor): """ Finds and marks faces in a base64 encoded jpg image function Inputs: b64image: Image to analyze Outputs: b64image: New image with all detected faces marked """ @manage([]) def init(self): self.setup() def setup(self): self._object_counter = calvinsys.open(self, "image.facefinding") def did_migrate(self): self.setup() @stateguard(lambda self: calvinsys.can_write(self._object_counter)) @condition(action_input=['b64image']) def analyze(self, b64image): calvinsys.write(self._object_counter, b64image) @stateguard(lambda self: calvinsys.can_read(self._object_counter)) @condition(action_output=['b64image']) def report(self): image = calvinsys.read(self._object_counter) return (image, ) action_priority = (analyze, report) requires = ['image.facefinding'] test_calvinsys = { 'image.facefinding': { 'read': ["dummy_data_read"], 'write': ["dummy_data_write"] } } test_set = [{ 'inports': { 'b64image': ["dummy_data_write"] }, 'outports': { 'b64image': ["dummy_data_read"] } }]
class ImageSource(Actor): """ When token on input, get an image. Inputs: trigger: anything Outputs: b64image: generated image """ @manage(exclude=["_cam"]) def init(self): self.setup() def setup(self): self._cam = calvinsys.open(self, "image.source") def did_migrate(self): self.setup() def will_end(self): calvinsys.close(self._cam) @stateguard(lambda self: calvinsys.can_read(self._cam)) @condition(action_output=['b64image']) def send_image(self): image = calvinsys.read(self._cam) return (image, ) @stateguard(lambda self: calvinsys.can_write(self._cam)) @condition(action_input=['trigger']) def fetch_image(self, trigger): calvinsys.write(self._cam, None) action_priority = (fetch_image, send_image) requires = ['image.source'] test_calvinsys = {'image.source': {'read': [1,0,1,0,0,1,0,1], 'write': [None, None, None, None]}} test_set = [ { 'inports': {'trigger': [True, 1, "a", 0]}, 'outports': {'b64image': [1,0,1,0,0,1,0,1]} } ]
class ObjectCounter(Actor): """ Counts objects in a base64 encoded jpg image Inputs: b64image: Image to analyze Outputs: objects: number of objects found in image """ @manage([]) def init(self): self.setup() def setup(self): self._object_counter = calvinsys.open(self, "image.objectdetection") def did_migrate(self): self.setup() @stateguard(lambda self: calvinsys.can_write(self._object_counter)) @condition(action_input=['b64image']) def analyze(self, b64image): calvinsys.write(self._object_counter, b64image) @stateguard(lambda self: calvinsys.can_read(self._object_counter)) @condition(action_output=['objects']) def report(self): objects = calvinsys.read(self._object_counter) return (objects, ) action_priority = (analyze, report) requires = ['image.objectdetection'] test_calvinsys = { 'image.objectdetection': { 'read': ["dummy_data_read"], 'write': ["dummy_data_write"] } } test_set = [{ 'inports': { 'b64image': ["dummy_data_write"] }, 'outports': { 'objects': ["dummy_data_read"] } }]
class ClassicDelay(Actor): """ After first token, pass on token once every 'delay' seconds. Input : token: anything Outputs: token: anything """ @manage(['timer', 'delay', 'started']) def init(self, delay): self.delay = delay self.timer = calvinsys.open(self, "sys.timer.repeating") self.started = False @stateguard( lambda self: not self.started and calvinsys.can_write(self.timer)) @condition(['token'], ['token']) def start_timer(self, token): self.started = True calvinsys.write(self.timer, self.delay) return (token, ) @stateguard(lambda self: calvinsys.can_read(self.timer)) @condition(['token'], ['token']) def passthrough(self, token): calvinsys.read(self.timer) return (token, ) action_priority = (start_timer, passthrough) requires = ['sys.timer.repeating'] test_kwargs = {'delay': 20} test_calvinsys = { 'sys.timer.repeating': { 'read': ["d", "u", "m", "m", "y"], 'write': [20] } } test_set = [{ 'inports': { 'token': ["a", "b", 1] }, 'outports': { 'token': ["a", "b", 1] } }]
class Trigger(Actor): """ Pass on given _data_ every _tick_ seconds Outputs: data: given data """ @manage(['timer', 'tick', 'data', 'started']) def init(self, tick, data): self.tick = tick self.data = data self.timer = None self.started = False self.setup() def setup(self): self.timer = calvinsys.open(self, "sys.timer.repeating") def start(self): calvinsys.write(self.timer, self.tick) self.started = True @stateguard(lambda self: not self.started and calvinsys.can_write(self.timer)) @condition([], ['data']) def start_timer(self): self.start() return (self.data, ) @stateguard(lambda self: calvinsys.can_read(self.timer)) @condition([], ['data']) def trigger(self): calvinsys.read(self.timer) # Ack return (self.data, ) action_priority = (start_timer, trigger) requires = ['sys.timer.repeating'] test_kwargs = {'tick': 12, 'data': "data_to_forward"} test_calvinsys = {'sys.timer.repeating': {'read': ["dummy_data_read"], 'write': [12]}} test_set = [ { 'outports': {'data': ["data_to_forward"]} } ]
class Sink(Actor): """ Data sink - usually some form of permanent storage input: data: a list of json structures to be saved """ @manage([]) def init(self): self.sink = calvinsys.open(self, "data.sink") @stateguard(lambda self: calvinsys.can_write(self.sink)) @condition(["data"], []) def write(self, data): calvinsys.write(self.sink, data) action_priority = (write, ) requires = ['data.sink']
class TriggeredTemperature(Actor): """ Measure temperature. Inputs: trigger : any token triggers meausurement Outputs: centigrade : temperature, in centigrade """ @manage([]) def init(self): self.setup() def setup(self): self._temperature = calvinsys.open(self, "io.temperature") def teardown(self): if self._temperature: calvinsys.close(self._temperature) self._temperature = None def will_migrate(self): self.teardown() def did_migrate(self): self.setup() def will_end(self): self.teardown() @stateguard(lambda self: calvinsys.can_read(self._temperature)) @condition([], ['centigrade']) def read_measurement(self): temperature = calvinsys.read(self._temperature) return (temperature, ) @stateguard(lambda self: calvinsys.can_write(self._temperature)) @condition(['trigger'], []) def start_measurement(self, _): calvinsys.write(self._temperature, True) action_priority = (read_measurement, start_measurement) requires = ['io.temperature']
class Temperature(Actor): """ Measure temperature. Takes the frequency of measurements, in Hz, as input. Outputs: centigrade : temperature, in centigrade """ @manage(['frequency']) def init(self, frequency): self.frequency = frequency self.setup() def setup(self): self._temperature = calvinsys.open(self, "io.temperature") self.use("calvinsys.events.timer", shorthand="timer") self._timer = self['timer'].once(0) def will_migrate(self): calvinsys.close(self._temperature) self._temperature = None def did_migrate(self): self.setup() def will_end(self): if self._temperature: calvinsys.close(self._temperature) @stateguard(lambda self: calvinsys.can_read(self._temperature)) @condition([], ['centigrade']) def read_measurement(self): temperature = calvinsys.read(self._temperature) self._timer = self['timer'].once(1.0 / self.frequency) return (temperature, ) @stateguard(lambda self: self._timer.triggered and calvinsys.can_write( self._temperature)) @condition([], []) def start_measurement(self): self._timer.ack() calvinsys.write(self._temperature, True) action_priority = (read_measurement, start_measurement) requires = ['io.temperature', 'calvinsys.events.timer']
class MQTTPublisher(Actor): """ Publish all incoming messages to given broker" Arguments: hostname: <ip/name of of mqtt broker>, port: <port to use on mqtt broker>, Settings is a dictionary with optional arguments. { "tls": { "ca_certs": <ca certs>, "certfile": <certfile>, "keyfile": <keyfile>, "tls_version": <tls version>, "ciphers": <ciphers> }, "auth": { "username": <username "password": <password> }, "will": { "topic": <topic>, "payload": <payload> }, "transport": <tcp or websocket>, "client_id": <id of this mqtt client> "topic": <prefix all outgoing message topics with this> } input: topic : topic of message payload: payload of message """ @manage(['mqtt']) def init(self, hostname, port, settings): if not settings: settings = {} self.mqtt = calvinsys.open(self, "mqtt.publish", hostname=hostname, port=port, **settings) @stateguard(lambda self: calvinsys.can_write(self.mqtt)) @condition(action_input=['topic', 'payload']) def send_message(self, topic, payload): calvinsys.write(self.mqtt, {"topic": topic, "payload": payload}) action_priority = (send_message, ) requires = ['mqtt.publish']
def setup(self): self.pwm = calvinsys.open(self, "io.pwm") if self.dutycycle and calvinsys.can_write(self.pwm): calvinsys.write(self.pwm, self.dutycycle)
def timeout(self): calvinsys.read(self.schedule) # ack calvinsys.can_write(self.schedule) calvinsys.write(self.schedule, 0) #reset return (self.data, )