diff --git a/BirdDog Mini Encoder or Decoder/script.py b/BirdDog Mini Encoder or Decoder/script.py new file mode 100644 index 0000000..05b4eb8 --- /dev/null +++ b/BirdDog Mini Encoder or Decoder/script.py @@ -0,0 +1,237 @@ +''' +**BirdDog Mini** encoder/decoder + +`rev 2.2405` + +* use Sources parameter when decoder + +_changelog_ + + * _rev 2.240514 JP belatedly added to repo_ + * _rev 1.200214 JP first created_ + +''' + +# + +local_event_Source = LocalEvent({'group': 'Switching', 'order': next_seq(), 'schema': {'type': 'string'}}) +# ... individual source will attach emit handlers + +local_event_SourceUnknown = LocalEvent({'title': 'Unknown', 'group': 'Sources', 'order': next_seq(), 'schema': {'type': 'boolean'}}) + +_srcLocations_byName = { } # e.g. { '1': { ip: '1.2.2.2', port: 23, .... } } +_srcNames_byNetworkLocation = { } # e.g. { '1.2.2.2:23': '1', ... } + +def main(): + if param_disabled: + console.warn('Disabled; nothing to do!') + return + + if len(param_sources or local_event_Sources.getArg() or EMPTY) == 0: + console.warn('No sources configured; nothing to do!') + return + + initSources() + + console.info('Will monitor and control [%s]' % param_ipAddress) + console.info('%s sources listed' % len(_srcLocations_byName)) + +local_event_Sources = LocalEvent({'group': 'Config', 'schema': {'type': 'array', 'items': {'type': 'object', 'properties': { + 'name': {'type': 'string', 'order': 1}, + 'location': {'type': 'object', 'order': 2, 'properties': { + 'ip': {'type': 'string', 'order': 1}, + 'port': {'type': 'integer', 'order': 2}, + 'name': {'type': 'string', 'order': 3} }}}}}}) + +def remote_event_Sources(arg): + if len(param_sources or EMPTY) > 0: + console.warn('Ignoring new remote source list; parameter in use instead') + return + + console.warn('Received new source list! [%s]' % arg) + local_event_Sources.emit(arg) + + console.warn('Node will self-restart!') + _node.restart() + + +def initSources(): + sources = param_sources or local_event_Sources.getArg() or EMPTY + + if len(sources) == 0: + console.warn('No sources specified') + return + + for srcInfo in sources: + initSource(srcInfo) + + # also handle unknown sources + + def handler(arg): + local_event_SourceUnknown.emit(arg not in _srcLocations_byName) + + local_event_Source.addEmitHandler(handler) + + # emit sources for slave config + local_event_Sources.emit(sources) + +def initSource(srcInfo): + name = srcInfo['name'] + location = srcInfo['location'] + + if not name or not location: + raise Warning("incomplete config - missing name or location") + + networkLocation = '%s:%s' % (location['ip'], location['port']) # will be used as a key later + + # the signal + activeSrcSignal = Event('Source %s' % name, {'title': '"%s"' % name, 'group': 'Sources', 'order': next_seq(), 'schema': {'type': 'boolean'}}) + + # emit boolean on source change + def handler(arg): + activeSrcSignal.emit(arg == name) + + local_event_Source.addEmitHandler(handler) + + # the action + def actionHandler(arg): + SwitchTo.call(location) + + srcSwitch = Action('Source %s' % name, actionHandler, {'title': '"%s"' % name, 'group': 'Sources', 'order': next_seq()}) + + _srcLocations_byName[name] = location + _srcNames_byNetworkLocation[networkLocation] = name # e.g. { '1.2.2.2:23': '1', ... } + +# --> + +@local_action({'group': 'Switching', 'order': next_seq(), 'schema': {'type': 'object', 'properties': { + 'ip': {'type': 'string', 'order': 1}, + 'port': {'type': 'integer', 'order': 2}, + 'name': {'type': 'string', 'order': 3}}}}) +def SwitchTo(arg): + console.info('SwitchTo(%s) called' % arg) + ip = arg['ip'] + port = arg['port'] + result = request('connectTo', {'connectToIp': ip, 'port': port, 'sourceName': arg['name']}) + log(2, 'SwitchTo result [%s]' % result) + + # todo check result + + # assume good + + networkLocation = '%s:%s' % (ip, port) + name = _srcNames_byNetworkLocation.get(networkLocation) + + local_event_Source.emit(name if name else 'Unknown') + +@local_action({'group': 'Switching', 'order': next_seq()}) +def PollSource(ignore): + log(2, 'PollSource') + resp = request('connectTo') + + global _lastReceive + _lastReceive = system_clock() + + ip = resp['connectToIp'] + port = resp['port'] + + networkLocation = '%s:%s' % (ip, port) + name = _srcNames_byNetworkLocation.get(networkLocation) + + local_event_Source.emit(name if name else 'Unknown') + + log(2, 'PollSource resp [%s]' % resp) + +Timer(lambda: PollSource.call(), 15, 5) # every 15s, first after 5s + +def request(endPoint, arg=None): + # e.g. curl http://birddog-1be4d:8080/connectTo -H "Content-Type: application/json" -d "{\"connectToIp\":\"192.168.178.151\",\"port\":5962,\"sourceName\":\"MM-LL-LABPTZ (CAM)\"}" -v + post = None if arg == None else json_encode(arg) + + url = 'http://%s:8080/%s' % (param_ipAddress, endPoint) + + log(3, 'url:%s%s' % (url, ' post:%s' % post if post else '')) + + result = get_url(url, headers={'Content-Type': 'application/json'}, post=post) + + return json_decode(result) if len(result or BLANK) > 0 else None + +# + + +#