esp_prov.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #!/usr/bin/env python
  2. #
  3. # Copyright 2018 Espressif Systems (Shanghai) PTE LTD
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. #
  17. from __future__ import print_function
  18. import argparse
  19. import time
  20. import os
  21. import sys
  22. try:
  23. import security
  24. import transport
  25. import prov
  26. except ImportError:
  27. idf_path = os.environ['IDF_PATH']
  28. sys.path.insert(0, idf_path + "/components/protocomm/python")
  29. sys.path.insert(1, idf_path + "/tools/esp_prov")
  30. import security
  31. import transport
  32. import prov
  33. # Set this to true to allow exceptions to be thrown
  34. config_throw_except = False
  35. def on_except(err):
  36. if config_throw_except:
  37. raise RuntimeError(err)
  38. else:
  39. print(err)
  40. def get_security(secver, pop=None, verbose=False):
  41. if secver == 1:
  42. return security.Security1(pop, verbose)
  43. elif secver == 0:
  44. return security.Security0(verbose)
  45. return None
  46. def get_transport(sel_transport, softap_endpoint=None, ble_devname=None):
  47. try:
  48. tp = None
  49. if (sel_transport == 'softap'):
  50. tp = transport.Transport_Softap(softap_endpoint)
  51. elif (sel_transport == 'ble'):
  52. tp = transport.Transport_BLE(devname=ble_devname,
  53. service_uuid='0000ffff-0000-1000-8000-00805f9b34fb',
  54. nu_lookup={'prov-session': 'ff51',
  55. 'prov-config': 'ff52',
  56. 'proto-ver': 'ff53'
  57. })
  58. elif (sel_transport == 'console'):
  59. tp = transport.Transport_Console()
  60. return tp
  61. except RuntimeError as e:
  62. on_except(e)
  63. return None
  64. def version_match(tp, protover):
  65. try:
  66. response = tp.send_data('proto-ver', protover)
  67. if response != "SUCCESS":
  68. return False
  69. return True
  70. except RuntimeError as e:
  71. on_except(e)
  72. return None
  73. def establish_session(tp, sec):
  74. try:
  75. response = None
  76. while True:
  77. request = sec.security_session(response)
  78. if request is None:
  79. break
  80. response = tp.send_data('prov-session', request)
  81. if (response is None):
  82. return False
  83. return True
  84. except RuntimeError as e:
  85. on_except(e)
  86. return None
  87. def custom_config(tp, sec, custom_info, custom_ver):
  88. try:
  89. message = prov.custom_config_request(sec, custom_info, custom_ver)
  90. response = tp.send_data('custom-config', message)
  91. return (prov.custom_config_response(sec, response) == 0)
  92. except RuntimeError as e:
  93. on_except(e)
  94. return None
  95. def send_wifi_config(tp, sec, ssid, passphrase):
  96. try:
  97. message = prov.config_set_config_request(sec, ssid, passphrase)
  98. response = tp.send_data('prov-config', message)
  99. return (prov.config_set_config_response(sec, response) == 0)
  100. except RuntimeError as e:
  101. on_except(e)
  102. return None
  103. def apply_wifi_config(tp, sec):
  104. try:
  105. message = prov.config_apply_config_request(sec)
  106. response = tp.send_data('prov-config', message)
  107. return (prov.config_set_config_response(sec, response) == 0)
  108. except RuntimeError as e:
  109. on_except(e)
  110. return None
  111. def get_wifi_config(tp, sec):
  112. try:
  113. message = prov.config_get_status_request(sec)
  114. response = tp.send_data('prov-config', message)
  115. return prov.config_get_status_response(sec, response)
  116. except RuntimeError as e:
  117. on_except(e)
  118. return None
  119. if __name__ == '__main__':
  120. parser = argparse.ArgumentParser(description="Generate ESP prov payload")
  121. parser.add_argument("--ssid", dest='ssid', type=str,
  122. help="SSID of Wi-Fi Network", required=True)
  123. parser.add_argument("--passphrase", dest='passphrase', type=str,
  124. help="Passphrase of Wi-Fi network", default='')
  125. parser.add_argument("--sec_ver", dest='secver', type=int,
  126. help="Security scheme version", default=1)
  127. parser.add_argument("--proto_ver", dest='protover', type=str,
  128. help="Protocol version", default='V0.1')
  129. parser.add_argument("--pop", dest='pop', type=str,
  130. help="Proof of possession", default='')
  131. parser.add_argument("--softap_endpoint", dest='softap_endpoint', type=str,
  132. help="<softap_ip:port>, http(s):// shouldn't be included", default='192.168.4.1:80')
  133. parser.add_argument("--ble_devname", dest='ble_devname', type=str,
  134. help="BLE Device Name", default='')
  135. parser.add_argument("--transport", dest='provmode', type=str,
  136. help="provisioning mode i.e console or softap or ble", default='softap')
  137. parser.add_argument("--custom_config", help="Provision Custom Configuration",
  138. action="store_true")
  139. parser.add_argument("--custom_info", dest='custom_info', type=str,
  140. help="Custom Config Info String", default='<some custom info string>')
  141. parser.add_argument("--custom_ver", dest='custom_ver', type=int,
  142. help="Custom Config Version Number", default=2)
  143. parser.add_argument("-v","--verbose", help="increase output verbosity", action="store_true")
  144. args = parser.parse_args()
  145. print("==== Esp_Prov Version: " + args.protover + " ====")
  146. obj_security = get_security(args.secver, args.pop, args.verbose)
  147. if obj_security is None:
  148. print("---- Invalid Security Version ----")
  149. exit(1)
  150. obj_transport = get_transport(args.provmode, args.softap_endpoint, args.ble_devname)
  151. if obj_transport is None:
  152. print("---- Invalid provisioning mode ----")
  153. exit(2)
  154. print("\n==== Verifying protocol version ====")
  155. if not version_match(obj_transport, args.protover):
  156. print("---- Error in protocol version matching ----")
  157. exit(3)
  158. print("==== Verified protocol version successfully ====")
  159. print("\n==== Starting Session ====")
  160. if not establish_session(obj_transport, obj_security):
  161. print("---- Error in establishing session ----")
  162. exit(4)
  163. print("==== Session Established ====")
  164. if args.custom_config:
  165. print("\n==== Sending Custom config to esp32 ====")
  166. if not custom_config(obj_transport, obj_security, args.custom_info, args.custom_ver):
  167. print("---- Error in custom config ----")
  168. exit(5)
  169. print("==== Custom config sent successfully ====")
  170. print("\n==== Sending Wi-Fi credential to esp32 ====")
  171. if not send_wifi_config(obj_transport, obj_security, args.ssid, args.passphrase):
  172. print("---- Error in send Wi-Fi config ----")
  173. exit(6)
  174. print("==== Wi-Fi Credentials sent successfully ====")
  175. print("\n==== Applying config to esp32 ====")
  176. if not apply_wifi_config(obj_transport, obj_security):
  177. print("---- Error in apply Wi-Fi config ----")
  178. exit(7)
  179. print("==== Apply config sent successfully ====")
  180. while True:
  181. time.sleep(5)
  182. print("\n==== Wi-Fi connection state ====")
  183. ret = get_wifi_config(obj_transport, obj_security)
  184. if (ret == 1):
  185. continue
  186. elif (ret == 0):
  187. print("==== Provisioning was successful ====")
  188. else:
  189. print("---- Provisioning failed ----")
  190. break