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.

cli.py 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #!/usr/bin/env python3
  2. # builtins
  3. import click
  4. from datetime import datetime
  5. import importlib
  6. import time
  7. import json
  8. import os
  9. import re
  10. import sys
  11. import time
  12. import urllib
  13. import uvicorn
  14. import requests
  15. from pyheatpump.logger import logger_init
  16. from pyheatpump.models import *
  17. CONTEXT_SETTINGS={
  18. 'default_map':{'run': {}}
  19. }
  20. @click.group(invoke_without_command=True, context_settings=CONTEXT_SETTINGS)
  21. @click.option('--version', is_flag=True)
  22. @click.pass_context
  23. def cli(ctx, version):
  24. """
  25. if version:
  26. from pyheatpump import version
  27. return click.echo(pyheatpump.version())
  28. """
  29. pass
  30. @click.option('--host', default=None)
  31. @click.option('--port', default=None)
  32. @cli.command()
  33. def run(host, port):
  34. logger = logger_init()
  35. from .config import (API_HOST, API_PORT)
  36. if not host:
  37. host = API_HOST
  38. if not port:
  39. port = API_PORT
  40. log_level = 'info'
  41. click.echo('Launching PyHeatpump application')
  42. uvicorn.run('pyheatpump.app:application',
  43. host=host,
  44. port=int(port),
  45. log_level=log_level,
  46. workers=1)
  47. def fetch(types=[]):
  48. logger = logger_init()
  49. from pyheatpump import modbus
  50. try:
  51. if len(types) == 0:
  52. var_types = VariableType.getall()
  53. else:
  54. var_types = {}
  55. for label, var_type in VariableType.getall().items():
  56. if label in type or var_type.slabel in type:
  57. var_types[label] = var_type
  58. # Analog - float
  59. if 'Analog' in var_types.keys():
  60. analog = var_types['Analog']
  61. logger.info('Read analog variables in registers [{}, {}]'.format(
  62. analog.start_address, analog.end_address
  63. ))
  64. res = modbus.read_holding_registers(analog.start_address, analog.end_address)
  65. logger.debug(f'analog length : {len(res)}')
  66. for r in range(len(res)):
  67. var = Variable(**{
  68. 'type': analog,
  69. 'address': r + analog.start_address})
  70. if not var.exists():
  71. logger.info('Insert variable {}:{}'.format(
  72. var.type, var.address))
  73. var.insert()
  74. val = VariableValue(**{
  75. 'type': var.type,
  76. 'address': var.address,
  77. 'value': res[r]})
  78. val.insert()
  79. # Integer - int
  80. if 'Integer' in var_types.keys():
  81. integer = var_types['Integer']
  82. logger.info('Read integer variables in registers [{}, {}]'.format(
  83. integer.start_address, integer.end_address
  84. ))
  85. res = modbus.read_holding_registers(integer.start_address, integer.end_address)
  86. logger.debug(f'integer length : {len(res)}')
  87. for r in range(len(res)):
  88. var = Variable(**{
  89. 'type': integer,
  90. 'address': r + integer.start_address})
  91. if not var.exists():
  92. logger.info('Insert variable {}:{}'.format(
  93. var.type, var.address))
  94. var.insert()
  95. val = VariableValue(**{
  96. 'type': var.type,
  97. 'address': var.address,
  98. 'value': res[r]})
  99. val.insert()
  100. # Digital - bool
  101. if 'Digital' in var_types.keys():
  102. digital = var_types['Digital']
  103. logger.info('Read digital variables in coils [{}, {}]'.format(
  104. digital.start_address, digital.end_address
  105. ))
  106. res = modbus.read_coils(digital.start_address, digital.end_address)
  107. logger.debug(f'digital length : {len(res)}')
  108. for r in range(len(res)):
  109. var = Variable(**{
  110. 'type': digital,
  111. 'address': r + digital.start_address})
  112. if not var.exists():
  113. logger.info('Insert variable {}:{}'.format(
  114. var.type, var.address))
  115. var.insert()
  116. val = VariableValue(**{
  117. 'type': var.type,
  118. 'address': var.address,
  119. 'value': res[r]})
  120. val.insert()
  121. logger.info('Successfully read all variables')
  122. except Exception as exc:
  123. logger.error(exc)
  124. if modbus.serial_conn:
  125. modbus.serial_conn.close()
  126. @click.option('--since', is_flag=True)
  127. @cli.command()
  128. def supervise(since):
  129. logger = logger_init()
  130. build_url = lambda d: '{scheme}://{hostname}:{port}{path}'.format(**d)
  131. from .config import config, mac_address_init, get_last_update, set_last_update
  132. mac_address = config.get('heatpump','mac_address')
  133. if not re.match('^(([0-9a-f]{2}):?){6}$', mac_address, re.I):
  134. mac_address = mac_address_init()
  135. from .models.heatpump import Heatpump
  136. if not since:
  137. last_update = 0
  138. else:
  139. last_update = get_last_update()
  140. base_url = {
  141. 'scheme':config.get('supervisor', 'scheme'),
  142. 'hostname':config.get('supervisor', 'host'),
  143. 'port':config.getint('supervisor', 'port')
  144. }
  145. get_path = '/'.join((
  146. config.get('supervisor', 'get_path'),
  147. Heatpump(mac_address).macformat
  148. ))
  149. get_url = {
  150. **base_url,
  151. **{'path': get_path}
  152. }
  153. get_resp = requests.get(
  154. url=build_url(get_url),
  155. verify=False
  156. )
  157. control_data = get_resp.json()
  158. if Heatpump(mac_address).control(control_data):
  159. logger.info('GET to supervisor succeded : updated values')
  160. else:
  161. logger.warn('Unable to set data from supervisor\n{}'.format(control_data))
  162. # Récupération de toutes les variables en modbus
  163. fetch()
  164. post_packets = [
  165. Heatpump(mac_address, last_update, ['Analog']).packet,
  166. Heatpump(mac_address, last_update, ['Digital']).packet,
  167. Heatpump(mac_address, last_update, ['Integer']).packet
  168. ]
  169. post_url = {
  170. **base_url,
  171. **{'path': config.get('supervisor', 'post_path')}
  172. }
  173. logger.info(build_url(post_url))
  174. for packet in post_packets:
  175. logger.debug('Will send %s', packet)
  176. post_resp = requests.post(
  177. url=build_url(post_url),
  178. json=packet,
  179. verify=False,
  180. timeout=200
  181. )
  182. if post_resp.status_code == 200:
  183. logger.info('POST to supervisor succeeded')
  184. continue
  185. logger.info('POST to supervisor failed')
  186. set_last_update(int(datetime.now().strftime('%s')))