Projet de remplacement du "RPiPasserelle" d'Otec.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

config.py 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #!/usr/bin/env python3
  2. import os
  3. import re
  4. from datetime import datetime
  5. from configparser import ConfigParser
  6. from starlette.requests import Request
  7. from starlette.routing import Route, Router
  8. from starlette.responses import PlainTextResponse, JSONResponse
  9. from pprint import pprint
  10. import uvicorn
  11. import json
  12. from pyheatpump.logger import logger_init
  13. logger = logger_init()
  14. default_config = {
  15. 'heatpump': {
  16. 'serial_port': '/dev/ttyUSB0',
  17. 'baudrate': 19200,
  18. 'mac_address': 'None',
  19. 'ip_address': 'dhcp',
  20. 'read_only': 'False',
  21. 'database': '/var/run/pyheatpump/pyheatpump.sqlite3'
  22. },
  23. 'supervisor': {
  24. 'scheme': 'http',
  25. 'host': '127.0.0.1',
  26. 'port': 8008,
  27. 'certificate': 'None',
  28. 'get_path': '/',
  29. 'post_path': '/',
  30. 'interval': 10000,
  31. 'auth': 'None',
  32. 'initialization': str(datetime.now()),
  33. 'heatpump_id': 'None',
  34. 'last_update': 0
  35. },
  36. 'api': {
  37. 'host': '127.0.0.1',
  38. 'port': 80
  39. }
  40. }
  41. CONFIG_FILES=[
  42. '/etc/pyheatpump.ini',
  43. './pyheatpump.ini']
  44. config = ConfigParser()#default_section='heatpump')
  45. config.read_dict(default_config)
  46. config.read(filenames=CONFIG_FILES)
  47. API_HOST=config.get('api', 'host')
  48. API_PORT=config.get('api', 'port')
  49. def save_config():
  50. with open(CONFIG_FILES[-1], 'w') as conf_file:
  51. config.write(conf_file)
  52. def get_mac():
  53. return get_config_dict()['heatpump', 'mac_address']
  54. def mac_address_init():
  55. from netifaces import gateways, ifaddresses, AF_INET, AF_LINK
  56. interface = gateways()['default'][AF_INET][1]
  57. if len(ifaddresses(interface)) == 0:
  58. logger.error("Can't find interface")
  59. sys.exit(1)
  60. if len(ifaddresses(interface)[AF_LINK]) == 0:
  61. logger.error("Can't find interface")
  62. sys.exit(1)
  63. addr = ifaddresses(interface)[AF_LINK][0]['addr']
  64. config.set('heatpump', 'mac_address', addr)
  65. save_config()
  66. return addr
  67. def get_config_dict():
  68. c = config
  69. return dict([ (s, dict([ (i, j) for i, j in c.items(s) ]) ) for s in c.sections() ])
  70. async def get_config(request):
  71. return JSONResponse(get_config_dict())
  72. async def set_config(request):
  73. body = await request.json()
  74. d_body = json.loads(body)
  75. #return PlainTextResponse(body)
  76. for sect in d_body.keys():
  77. if type(d_body[sect]) is not dict:
  78. continue
  79. for item in d_body[sect].keys():
  80. if not config.has_option(sect, item):
  81. raise HTTPException(404, f'The option {sect}.{item} does not exists')
  82. else:
  83. config.set(sect, item, value=d_body[sect][item])
  84. save_config()
  85. return PlainTextResponse('OK')
  86. async def config_route(request, *args, **kwargs):
  87. if request['method'] == 'GET':
  88. return await get_config(request)
  89. elif request['method'] == 'POST':
  90. return await set_config(request)
  91. async def mac_route(request, *args, **kwargs):
  92. if request['method'] == 'GET':
  93. return PlainTextResponse(get_mac())
  94. elif request['method'] == 'POST':
  95. body = await request.body()
  96. mac_address = body.decode()
  97. if len(mac_address) == 0:
  98. mac_address = mac_address_init()
  99. elif re.match('^([0-9a-f]{2}:?){6}$',
  100. mac_address, re.I) is not None:
  101. config.set('heatpump','mac_address',mac_address)
  102. save_config()
  103. else:
  104. print(f'Wrong mac format : {mac_address}')
  105. return PlainTextResponse(' '.join((
  106. 'Current ->',
  107. get_mac(),
  108. ', New -> ', mac_address)))
  109. def get_last_update():
  110. return config.get('supervisor', 'last_update')
  111. def set_last_update(last_update: int=0):
  112. config.set('supervisor', 'last_update', str(last_update))
  113. save_config()
  114. return get_last_update()
  115. async def last_update_route(request, *args, **kwargs):
  116. """
  117. last_update :
  118. == 0 : since current date - interval
  119. < 0 : since current_date + last_update - interval
  120. > 0 : since current_data - last_update - interval (same behaviour as < 0)
  121. """
  122. if type(request) != Request or request['method'] == 'GET':
  123. return PlainTextResponse(get_last_update())
  124. elif request['method'] == 'POST':
  125. body = await request.body()
  126. last_update = int(body.decode() or 0)
  127. print(f'Last update set : {last_update}')
  128. if last_update == 0:
  129. print('Reset last update to current time')
  130. last_update = int(datetime.now().strftime('%s'))
  131. elif last_update <= 0:
  132. print('Forward of {last_update} seconds')
  133. last_update = int(datetime.now().strftime('%s')) + last_update
  134. else:
  135. print('Rewind of {last_update} seconds')
  136. last_update = int(datetime.now().strftime('%s')) - last_update
  137. return PlainTextResponse(str(set_last_update(last_update)))
  138. ROUTES=[
  139. Route('/', config_route, methods=['GET', 'POST']),
  140. Route('/mac', mac_route, methods=['GET', 'POST']),
  141. Route('/last_update', last_update_route, methods=['GET', 'POST'])
  142. ]
  143. app = Router(routes=ROUTES)
  144. if __name__ == '__main__':
  145. uvicorn.run('pyHeatpump:conf.app',
  146. host='127.0.0.1',
  147. port=8000)