IotObject.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. import json
  4. from abc import ABCMeta,abstractmethod
  5. import boto3
  6. from Ansjer.config import AWS_IOT_SES_ACCESS_CHINA_REGION, AWS_IOT_SES_ACCESS_CHINA_ID, AWS_IOT_SES_ACCESS_CHINA_SECRET, \
  7. AWS_IOT_SES_ACCESS_FOREIGN_REGION_AMERICA, AWS_IOT_SES_ACCESS_FOREIGN_ID, AWS_IOT_SES_ACCESS_FOREIGN_SECRET, \
  8. AWS_IOT_SES_ACCESS_FOREIGN_REGION_EUROPE, AWS_IOT_SES_ACCESS_FOREIGN_REGION_ASIA, AWS_IOT_SES_ACCESS_CHINA_ROLE, \
  9. AWS_IOT_SES_ACCESS_FOREIGN_ROLE
  10. class IOTObject(metaclass=ABCMeta):
  11. @abstractmethod
  12. def create_provisioning_claim(self, templateName):
  13. pass
  14. @abstractmethod
  15. def create_keys_and_certificate(self, uid):
  16. pass
  17. class IOTClient(IOTObject):
  18. def __init__(self, region_id=1):
  19. if region_id == 1:
  20. # 中国宁夏
  21. self.client = boto3.client('iot', region_name=AWS_IOT_SES_ACCESS_CHINA_REGION,
  22. aws_access_key_id=AWS_IOT_SES_ACCESS_CHINA_ID,
  23. aws_secret_access_key=AWS_IOT_SES_ACCESS_CHINA_SECRET)
  24. # 终端节点: https://cn-northwest-1.console.amazonaws.cn/iot/home?region=cn-northwest-1#/settings
  25. self.endpoint = 'a250bbr0p9u7as-ats.iot.cn-northwest-1.amazonaws.com.cn'
  26. self.iotrole = AWS_IOT_SES_ACCESS_CHINA_ROLE
  27. if region_id == 2:
  28. # 亚太新加坡
  29. self.client = boto3.client('iot', region_name=AWS_IOT_SES_ACCESS_FOREIGN_REGION_ASIA,
  30. aws_access_key_id=AWS_IOT_SES_ACCESS_FOREIGN_ID,
  31. aws_secret_access_key=AWS_IOT_SES_ACCESS_FOREIGN_SECRET)
  32. self.endpoint = 'a2rqy12o004ad8-ats.iot.ap-southeast-1.amazonaws.com'
  33. self.iotrole = AWS_IOT_SES_ACCESS_FOREIGN_ROLE
  34. if region_id == 3:
  35. # 美东弗吉尼亚
  36. self.client = boto3.client('iot', region_name=AWS_IOT_SES_ACCESS_FOREIGN_REGION_AMERICA,
  37. aws_access_key_id=AWS_IOT_SES_ACCESS_FOREIGN_ID,
  38. aws_secret_access_key=AWS_IOT_SES_ACCESS_FOREIGN_SECRET)
  39. self.endpoint = 'a2rqy12o004ad8-ats.iot.us-east-1.amazonaws.com'
  40. self.iotrole = AWS_IOT_SES_ACCESS_FOREIGN_ROLE
  41. if region_id == 4:
  42. # 西欧爱尔兰
  43. self.client = boto3.client('iot', region_name=AWS_IOT_SES_ACCESS_FOREIGN_REGION_EUROPE,
  44. aws_access_key_id=AWS_IOT_SES_ACCESS_FOREIGN_ID,
  45. aws_secret_access_key=AWS_IOT_SES_ACCESS_FOREIGN_SECRET)
  46. self.endpoint = 'a2rqy12o004ad8-ats.iot.eu-west-1.amazonaws.com'
  47. self.iotrole = AWS_IOT_SES_ACCESS_FOREIGN_ROLE
  48. def create_provisioning_claim(self, templateName):
  49. result = self.client.create_provisioning_claim(templateName=templateName)
  50. res = {
  51. 'certificateId': result['certificateId'],
  52. 'certificatePem': result['certificatePem'],
  53. 'publicKey': result['keyPair']['PublicKey'],
  54. 'privateKey': result['keyPair']['PrivateKey'],
  55. 'endpoint': self.endpoint
  56. }
  57. return res
  58. def register_to_iot_core(self, ThingNameSuffix, thingGroup, response):
  59. try:
  60. result = self.client.create_keys_and_certificate(setAsActive=True)
  61. res = {
  62. 'certificateId': result['certificateId'],
  63. 'certificatePem': result['certificatePem'],
  64. 'publicKey': result['keyPair']['PublicKey'],
  65. 'privateKey': result['keyPair']['PrivateKey'],
  66. 'endpoint': self.endpoint
  67. }
  68. # 搜索是否存在该物品组
  69. thing_groups_res = self.client.list_thing_groups(nextToken='', maxResults=1,
  70. namePrefixFilter=thingGroup, recursive=False)
  71. if thing_groups_res['thingGroups']:
  72. thingGroupName = thing_groups_res['thingGroups'][0]['groupName'] # 获取物品组名称
  73. else:
  74. attributes = {
  75. "update_time": "0"
  76. }
  77. thingGroupProperties = {
  78. "thingGroupDescription": "OTA",
  79. "attributePayload": {
  80. "attributes": attributes,
  81. "merge": False # 更新时覆盖掉而不是合并
  82. }
  83. }
  84. create_thing_group_res = self.client.create_thing_group(thingGroupName=thingGroup,
  85. thingGroupProperties=thingGroupProperties)
  86. thingGroupName = create_thing_group_res['thingGroupName'] # 获取物品组名称
  87. print('物品组:', thingGroupName)
  88. # 根据证书ID注册物品和策略
  89. templateBody = {
  90. "Parameters": {
  91. "ThingName": {
  92. "Type": "String"
  93. },
  94. "SerialNumber": {
  95. "Type": "String"
  96. },
  97. "thingGroupName": {
  98. "Type": "String"
  99. },
  100. "AWS::IoT::Certificate::Id": {
  101. "Type": "String"
  102. }
  103. },
  104. "Resources": {
  105. "thing": {
  106. "Type": "AWS::IoT::Thing",
  107. "Properties": {
  108. "AttributePayload": {},
  109. # "ThingGroups" : ["v1-lightbulbs", {"Ref" : "DeviceLocation"}],
  110. "ThingName": {
  111. "Ref": "ThingName"
  112. },
  113. "ThingGroups": [{"Ref": "thingGroupName"}]
  114. },
  115. "OverrideSettings": {
  116. "AttributePayload": "MERGE",
  117. "ThingTypeName": "REPLACE",
  118. "ThingGroups": "DO_NOTHING"
  119. }
  120. },
  121. "certificate": {
  122. "Type": "AWS::IoT::Certificate",
  123. "Properties": {
  124. "CertificateId": {"Ref": "AWS::IoT::Certificate::Id"},
  125. "Status": "Active"
  126. }
  127. },
  128. "policy": {
  129. "Properties": {
  130. "PolicyName": "My_Iot_Policy"
  131. },
  132. "Type": "AWS::IoT::Policy"
  133. },
  134. }
  135. }
  136. ThingName = 'Ansjer_Device_' + ThingNameSuffix
  137. templateBody = json.dumps(templateBody)
  138. parameters = {"ThingName": ThingName,
  139. "thingGroupName": thingGroupName,
  140. "AWS::IoT::Certificate::Id": res['certificateId']}
  141. self.client.register_thing(
  142. templateBody=templateBody,
  143. parameters=parameters
  144. )
  145. topicsql = "SELECT * FROM 'my/things/" + ThingName + "/shadow/update_lwt'"
  146. self.client.create_topic_rule(
  147. ruleName= ThingName + '_LWT',
  148. topicRulePayload={
  149. "sql": topicsql,
  150. "ruleDisabled": False,
  151. "awsIotSqlVersion": "2016-03-23",
  152. 'actions': [
  153. {
  154. 'republish': {
  155. 'roleArn': self.iotrole,
  156. 'topic': '$$aws/things/' + ThingName + '/shadow/update',
  157. 'qos': 1
  158. }
  159. }
  160. ]
  161. }
  162. )
  163. return res, parameters
  164. except Exception as e:
  165. print(e)
  166. return response.json(500, repr(e))