diff --git a/fup-anemometer-user.py b/fup-anemometer-user.py new file mode 100755 index 0000000..27f932e --- /dev/null +++ b/fup-anemometer-user.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python3 +""" +OSC/Random Example: send random numbers to OSC. + +This example sends a pseudo-random number between 0 and 1024 +to the OSC receiver on UDP port 2222. +""" +from pythonosc import udp_client +from pythonosc import osc_message_builder +import time +import os +import sys +import time + +# import urllib library +import urllib.request +import urllib.error + +# import json +import json + +# import argparse +import argparse + +# Logging to file +import logging + +# Errors codes +OSC_no_error = 0 +OSC_error = 1 +OSC_meteobridge_url_error = 11 +OSC_meteobridge_http_error = 12 +OSC_meteobridge_nosensor_error = 20 +OSC_meteobridge_restart = 30 + +# Debug flags +debug_args_print = True +debug_json_print = True +debug_urllib_print = True +debug_restart_print = True +debug_osc = False +debug_working_directory = os.path.dirname(os.path.realpath(__file__)) + +# OSC Addresses +osc_error_addr = "/env_sensors/anemometer/error" +osc_speed_addr = "/env_sensors/anemometer/speed" +osc_battery_addr = "/env_sensors/anemometer/battery" +osc_age_addr = "/env_sensors/anemometer/age" +osc_signal_addr = "/env_sensors/anemometer/signal" + + +# define urllib timeout in seconds +url_timeout = 120 + +# max error number before self restart +# max_error_rst = 3 + +prod_flag = False +prod_working_directory = "/usr/local/com.fup.anemometre_daemon" + +meteobridge_template = "cgi-bin/template.cgi?template={%22time%22:%22[DD][MM][YYYY][hh][mm][ss]%22,%22speed%22:[wind0wind-act],%22lastspeed%22:[wind0wind-lastval],%22battery%22:[wind0lowbat-act.0],%22wind-age%22:[wind0wind-age],%22signal%22:[wind0signal-act.0]}" + +def send_osc_message(osc_sender, osc_address, osc_arg): + msg = osc_message_builder.OscMessageBuilder(address = osc_address) + msg.add_arg(osc_arg) + osc_sender.send(msg.build()) + +def main(meteobridge_url, meteobridge_user, meteobridge_passwd, max_host, max_port, errors_restart): + + error_counter = 0 + + oscSender = udp_client.UDPClient(max_host, max_port) + + meteobridge_sensor_req = meteobridge_url + meteobridge_template + + # Logging + logging.basicConfig(filename='fup_anemometer.log', encoding='utf-8', format='%(asctime)s-%(levelname)s:%(message)s', datefmt='%Y/%m/%d %H:%M:%S', level=logging.DEBUG) + logging.info("fup_anemometer started") + + while True: + + # http auth to meteobridge + passman = urllib.request.HTTPPasswordMgrWithDefaultRealm() + passman.add_password(None, meteobridge_url, meteobridge_user, meteobridge_passwd) + authhandler = urllib.request.HTTPBasicAuthHandler(passman) + opener = urllib.request.build_opener(authhandler) + urllib.request.install_opener(opener) + + try: + response = urllib.request.urlopen(meteobridge_sensor_req, timeout = url_timeout) + + except urllib.error.HTTPError as e: + if debug_urllib_print: + print('HTTP Error code: ', e.code) + logging.error("Get sensor datas from : " + meteobridge_url + " - HTTP Error code: " + str(e.code)) + error_counter += 1 + send_osc_message(oscSender, osc_error_addr, OSC_meteobridge_http_error) + # msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") + # msg.add_arg(OSC_meteobridge_http_error) + # oscSender.send(msg.build()) + # Sleep 5 seconds if error + time.sleep(5) + + except urllib.error.URLError as e: + if debug_urllib_print: + print('URL Error Reason: ', e.reason) + logging.error("Get sensor datas from : " + meteobridge_url + " - URL Error Reason: " + str(e.reason)) + error_counter += 1 + send_osc_message(oscSender, osc_error_addr, OSC_meteobridge_url_error) + # msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") + # msg.add_arg(OSC_meteobridge_url_error) + # oscSender.send(msg.build()) + # Sleep 5 seconds if error + time.sleep(5) + + else: + try: + data_json = json.loads(response.read()) + if debug_json_print == True: + print(data_json) + wind_speed = float(data_json["speed"]) + wind_lastspeed = float(data_json["lastspeed"]) + wind_batt = int(data_json["battery"]) + wind_age = int(data_json["wind-age"]) + wind_signal = int(data_json["signal"]) + + except json.JSONDecodeError as e: + if debug_json_print: + print("Invalid JSON syntax:", e) + logging.error("Decode JSON from : " + meteobridge_url + " - Invalid JSON syntax : " + str(e)) + error_counter += 1 + send_osc_message(oscSender, osc_error_addr, OSC_meteobridge_nosensor_error) + # msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") + # msg.add_arg(OSC_meteobridge_nosensor_error) + # oscSender.send(msg.build()) + # Sleep 5 seconds if error + time.sleep(5) + + else: + error_counter = 0 + + send_osc_message(oscSender, osc_speed_addr, wind_lastspeed) + # msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/speed") + # msg.add_arg(wind_lastspeed) + # oscSender.send(msg.build()) + + send_osc_message(oscSender, osc_battery_addr, wind_batt) + # msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/battery") + # msg.add_arg(wind_batt) + # oscSender.send(msg.build()) + + send_osc_message(oscSender, osc_age_addr, wind_age) + # msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/age") + # msg.add_arg(wind_age) + # oscSender.send(msg.build()) + + send_osc_message(oscSender, osc_signal_addr, wind_signal) + # msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/signal") + # msg.add_arg(wind_signal) + # oscSender.send(msg.build()) + + send_osc_message(oscSender, osc_error_addr, OSC_no_error) + # msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") + # msg.add_arg(OSC_no_error) + # oscSender.send(msg.build()) + + if debug_osc: + logging.debug("OSC datas sent") + # Sleep 2 seconds if no errors + time.sleep(2) + # Self restart + if error_counter >= errors_restart: + send_osc_message(oscSender, osc_error_addr, OSC_meteobridge_restart) + # msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") + # msg.add_arg(OSC_meteobridge_restart) + # oscSender.send(msg.build()) + time.sleep(1) + if debug_restart_print: + print("Current errors count : " + str(error_counter) + " / " + errors_restart + " max errors") + print("Too many errors restarting program ...") + logging.error("Current errors count : " + str(error_counter) + " / " + errors_restart + " max errors") + logging.error("Too many errors restarting program ...") + os.execv(sys.executable, ['python'] + sys.argv) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="FUP anemometer for OSC") + parser.add_argument('-url', '--url-meteobridge', default='http://192.168.0.39/') + parser.add_argument('-u', '--user-meteobridge', default='meteobridge') + parser.add_argument('-p', '--passwd-meteobridge',default='meteobridge') + parser.add_argument('-mh', '--max-host', default='localhost') + parser.add_argument('-mp','--max-port', default=2222, type=int) + parser.add_argument('-e', '--errors-restart', default=20, type=int) + + args = parser.parse_args() + + # if debug_args_print is True, print arguments + if debug_args_print: + print('Meteobridge URL:', args.url_meteobridge) + print('Meteobridge User:', args.user_meteobridge) + print('Meteobridge Password:', args.passwd_meteobridge) + print('OSC host:', args.max_host) + print('OSC port:', args.max_port) + print('Errors restart:', args.errors_restart) + + main(meteobridge_url=args.url_meteobridge, meteobridge_user=args.user_meteobridge, meteobridge_passwd=args.passwd_meteobridge, max_host=args.max_host, max_port=args.max_port, errors_restart=args.errors_restart) \ No newline at end of file diff --git a/fup-anemomoter-user.py b/fup-anemomoter-user.py deleted file mode 100644 index 40045e3..0000000 --- a/fup-anemomoter-user.py +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/env python3 -""" -OSC/Random Example: send random numbers to OSC. - -This example sends a pseudo-random number between 0 and 1024 -to the OSC receiver on UDP port 2222. -""" -from pythonosc import udp_client -from pythonosc import osc_message_builder -import time -import os -import sys -import time - -# import urllib library -import urllib.request -import urllib.error - -# import json -import json - -# import argparse -import argparse - -# Logging to file -import logging - -# Errors codes -OSC_no_error = 0 -OSC_error = 1 -OSC_meteobridge_auth_error = 10 -OSC_meteobridge_url_error = 11 -OSC_meteobridge_http_error = 12 -OSC_meteobridge_nosensor_error = 20 -OSC_meteobridge_restart = 30 - -debug_args_print = True -debug_json_print = True -debug_urllib_print = True -debug_restart_print = True -debug_osc = False -debug_working_directory = os.path.dirname(os.path.realpath(__file__)) - -# define urllib timeout in seconds -url_timeout = 10 - -# max error number before self restart -# max_error_rst = 3 - -prod_flag = False -prod_working_directory = "/usr/local/com.fup.anemometre_daemon" - -meteobridge_template = "cgi-bin/template.cgi?template={%22time%22:%22[DD][MM][YYYY][hh][mm][ss]%22,%22speed%22:[wind0wind-act],%22lastspeed%22:[wind0wind-lastval],%22battery%22:[wind0lowbat-act.0],%22wind-age%22:[wind0wind-age],%22signal%22:[wind0signal-act.0]}" - -def main(meteobridge_url, meteobridge_user, meteobridge_passwd, max_host, max_port, errors_restart): - - error_counter = 0 - - http_auth_status = False - - oscSender = udp_client.UDPClient(max_host, max_port) - - meteobridge_sensor_req = meteobridge_url + meteobridge_template - - # Logging - logging.basicConfig(filename='fup_anemometer.log', encoding='utf-8', format='%(asctime)s-%(levelname)s:%(message)s', datefmt='%Y/%m/%d %H:%M:%S', level=logging.DEBUG) - logging.info("fup_anemometer started") - - while True: - if http_auth_status == False: - # http log to meteobridge - passman = urllib.request.HTTPPasswordMgrWithDefaultRealm() - passman.add_password(None, meteobridge_url, meteobridge_user, meteobridge_passwd) - authhandler = urllib.request.HTTPBasicAuthHandler(passman) - opener = urllib.request.build_opener(authhandler) - urllib.request.install_opener(opener) - - try: - res = urllib.request.urlopen(meteobridge_url, timeout = url_timeout) - - except urllib.error.HTTPError as e: - if debug_urllib_print: - print('HTTP Error code: ', e.code) - logging.error("Authentification to " + meteobridge_url + " - HTTP Error code: " + str(e.code)) - error_counter += 1 - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") - msg.add_arg(OSC_meteobridge_http_error) - oscSender.send(msg.build()) - # Sleep 5 seconds if error - time.sleep(5) - # raise SystemExit(e) - - except urllib.error.URLError as e: - if debug_urllib_print: - print('URL Error Reason: ', e.reason) - logging.error("Authentification to " + meteobridge_url + " - URL Error Reason: " + str(e.reason)) - error_counter += 1 - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") - msg.add_arg(OSC_meteobridge_url_error) - oscSender.send(msg.build()) - # Sleep 5 seconds if error - time.sleep(5) - # raise SystemExit(e) - - else: - error_counter = 0 - res_body = res.read() - if debug_urllib_print: - print(res_body.decode('utf-8')) - http_auth_status = True - logging.info("HTTP authentification to " + meteobridge_url + " succesful") - # Sleep 2 seconds if no errors - time.sleep(2) - - - else: - try: - response = urllib.request.urlopen(meteobridge_sensor_req, timeout = url_timeout) - - except urllib.error.HTTPError as e: - if debug_urllib_print: - print('HTTP Error code: ', e.code) - logging.error("Get sensor datas from : " + meteobridge_url + " - HTTP Error code: " + str(e.code)) - error_counter += 1 - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") - msg.add_arg(OSC_meteobridge_http_error) - oscSender.send(msg.build()) - # Sleep 5 seconds if error - time.sleep(5) - - except urllib.error.URLError as e: - if debug_urllib_print: - print('URL Error Reason: ', e.reason) - logging.error("Get sensor datas from : " + meteobridge_url + " - URL Error Reason: " + str(e.reason)) - error_counter += 1 - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") - msg.add_arg(OSC_meteobridge_url_error) - oscSender.send(msg.build()) - # Sleep 5 seconds if error - time.sleep(5) - - else: - try: - data_json = json.loads(response.read()) - if debug_json_print == True: - print(data_json) - wind_speed = float(data_json["speed"]) - wind_lastspeed = float(data_json["lastspeed"]) - wind_batt = int(data_json["battery"]) - wind_age = int(data_json["wind-age"]) - wind_signal = int(data_json["signal"]) - - except json.JSONDecodeError as e: - if debug_json_print: - print("Invalid JSON syntax:", e) - logging.error("Decode JSON from : " + meteobridge_url + " - Invalid JSON syntax : " + str(e)) - error_counter += 1 - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") - msg.add_arg(OSC_meteobridge_nosensor_error) - oscSender.send(msg.build()) - # Sleep 5 seconds if error - time.sleep(5) - - else: - error_counter = 0 - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/speed") - msg.add_arg(wind_lastspeed) - oscSender.send(msg.build()) - - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/battery") - msg.add_arg(wind_batt) - oscSender.send(msg.build()) - - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/age") - msg.add_arg(wind_age) - oscSender.send(msg.build()) - - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/signal") - msg.add_arg(wind_signal) - oscSender.send(msg.build()) - - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") - msg.add_arg(OSC_no_error) - oscSender.send(msg.build()) - if debug_osc: - logging.debug("OSC datas sent") - # Sleep 2 seconds if no errors - time.sleep(2) - # Self restart - if error_counter >= int(errors_restart): - msg = osc_message_builder.OscMessageBuilder(address = "/env_sensors/anemometer/error") - msg.add_arg(OSC_meteobridge_restart) - oscSender.send(msg.build()) - time.sleep(1) - if debug_restart_print: - print("Current errors count : " + str(error_counter) + " / " + errors_restart + " max errors") - print("Too many errors restarting program ...") - logging.error("Current errors count : " + str(error_counter) + " / " + errors_restart + " max errors") - logging.error("Too many errors restarting program ...") - os.execv(sys.executable, ['python'] + sys.argv) - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="FUP anemometer for OSC") - parser.add_argument('-url', '--url-meteobridge', default='http://192.168.0.39/') - parser.add_argument('-u', '--user-meteobridge', default='meteobridge') - parser.add_argument('-p', '--passwd-meteobridge',default='meteobridge') - parser.add_argument('-mh', '--max-host', default='localhost') - parser.add_argument('-mp','--max-port', default=2222) - parser.add_argument('-e', '--errors-restart', default=20) - - args = parser.parse_args() - - # if debug_args_print is True, print arguments - if debug_args_print: - print('Meteobridge URL:', args.url_meteobridge) - print('Meteobridge User:', args.user_meteobridge) - print('Meteobridge Password:', args.passwd_meteobridge) - print('OSC host:', args.max_host) - print('OSC port:', args.max_port) - print('Errors restart:', args.errors_restart) - - main(meteobridge_url=args.url_meteobridge, meteobridge_user=args.user_meteobridge, meteobridge_passwd=args.passwd_meteobridge, max_host=args.max_host, max_port=args.max_port, errors_restart=args.errors_restart) \ No newline at end of file