CommonService.py 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. import base64
  2. import calendar
  3. import datetime
  4. import re
  5. import time
  6. from base64 import encodebytes
  7. from distutils.version import LooseVersion
  8. from pathlib import Path
  9. from random import Random
  10. import OpenSSL.crypto as ct
  11. import ipdb
  12. import requests
  13. import simplejson as json
  14. from dateutil.relativedelta import relativedelta
  15. from django.core import serializers
  16. from django.db.models import F
  17. from django.utils import timezone
  18. from django.utils.crypto import constant_time_compare
  19. from pyipip import IPIPDatabase
  20. from Ansjer.config import BASE_DIR, SERVER_DOMAIN_SSL, CONFIG_INFO, CONFIG_TEST, CONFIG_CN, SERVER_DOMAIN_TEST, \
  21. SERVER_DOMAIN_CN, SERVER_DOMAIN_US, CONFIG_US, CONFIG_EUR, SERVER_DOMAIN_LIST, SERVER_DOMAIN_EUR, ALEXA_DOMAIN, \
  22. ME_COUNTRY_ID_LIST, EA_COUNTRY_ID_LIST, RU_COUNTRY_ID_LIST
  23. from Controller.CheckUserData import RandomStr
  24. from Model.models import iotdeviceInfoModel, Device_Info, UIDModel, AppDeviceType, UIDCompanySerialModel, GatewayPush, \
  25. Device_User, UserExModel
  26. from Object.AWS.S3Email import S3Email
  27. from Object.ResponseObject import ResponseObject
  28. from Object.TokenObject import TokenObject
  29. class CommonService:
  30. # 高复用性函数类
  31. @staticmethod
  32. def get_kwargs(data=None):
  33. # 添加模糊搜索
  34. if data is None:
  35. data = {}
  36. kwargs = {}
  37. for (k, v) in data.items():
  38. if v is not None and v != u'':
  39. kwargs[k + '__icontains'] = v
  40. return kwargs
  41. @staticmethod
  42. def qs_to_dict(query_set):
  43. # 格式化query_set转dict
  44. sqlJSON = serializers.serialize('json', query_set)
  45. sqlList = json.loads(sqlJSON)
  46. sqlDict = dict(zip(["datas"], [sqlList]))
  47. return sqlDict
  48. # 格式化query_set转dict
  49. @staticmethod
  50. def request_dict_to_dict(request_dict):
  51. # 传参格式转换,键包含meta获取meta[]中的值,值'true'/'false'转为True,False
  52. key_list = []
  53. value_list = []
  54. for k, v in request_dict.items():
  55. key_list.append(k[k.index('[') + 1:k.index(']')] if 'meta' in k else k)
  56. if v == 'true':
  57. v = True
  58. elif v == 'false':
  59. v = False
  60. value_list.append(v)
  61. data_dict = dict(zip(key_list, value_list))
  62. print(data_dict)
  63. return data_dict
  64. # 获取文件大小
  65. @staticmethod
  66. def get_file_size(file_path='', suffix_type='', decimal_point=0):
  67. # for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
  68. # path = Path() / 'D:/TestServer/123444.mp4'
  69. path = Path() / file_path
  70. size = path.stat().st_size
  71. mb_size = 0.0
  72. if suffix_type == 'MB':
  73. mb_size = size / 1024.0 / 1024.0
  74. if decimal_point != 0:
  75. mb_size = round(mb_size, decimal_point)
  76. return mb_size
  77. @staticmethod
  78. def get_param_flag(data=None):
  79. # print(data)
  80. if data is None:
  81. data = []
  82. flag = True
  83. for v in data:
  84. if v is None:
  85. flag = False
  86. break
  87. return flag
  88. @staticmethod
  89. def get_ip_address(request):
  90. """
  91. 获取ip地址
  92. :param request:
  93. :return:
  94. """
  95. try:
  96. real_ip = request.META['HTTP_X_FORWARDED_FOR']
  97. clientIP = real_ip.split(",")[0]
  98. except:
  99. try:
  100. clientIP = request.META['REMOTE_ADDR']
  101. except Exception as e:
  102. clientIP = ''
  103. return clientIP
  104. # @获取一天每个小时的datetime.datetime
  105. @staticmethod
  106. def getTimeDict(times):
  107. time_dict = {}
  108. t = 0
  109. for x in range(24):
  110. if x < 10:
  111. x = '0' + str(x)
  112. else:
  113. x = str(x)
  114. a = times.strftime("%Y-%m-%d") + " " + x + ":00:00"
  115. time_dict[t] = timezone.datetime.strptime(a, '%Y-%m-%d %H:%M:%S')
  116. t += 1
  117. return time_dict
  118. # 根据ip获取地址
  119. @staticmethod
  120. def getAddr(ip):
  121. print('start_time=' + str(time.time()))
  122. base_dir = BASE_DIR
  123. # ip数据库
  124. db = IPIPDatabase(base_dir + '/DB/17monipdb.dat')
  125. addr = db.lookup(ip)
  126. # ModelService.add_tmp_log(addr)
  127. ts = addr.split('\t')[0]
  128. print('end_time=' + str(time.time()))
  129. return ts
  130. # 通过ip检索ipip指定信息 lang为CN或EN
  131. @staticmethod
  132. def getIpIpInfo(ip, lang, update=False):
  133. ipbd_dir = BASE_DIR + "/DB/mydata4vipday2.ipdb"
  134. db = ipdb.City(ipbd_dir)
  135. if update:
  136. rr = db.reload(ipbd_dir)
  137. info = db.find_map(ip, lang)
  138. return info
  139. @staticmethod
  140. def getUserID(userPhone='13800138000', getUser=True, setOTAID=False, μs=True):
  141. if μs == True:
  142. if getUser == True:
  143. timeID = str(round(time.time() * 1000000))
  144. userID = timeID + userPhone
  145. return userID
  146. else:
  147. if setOTAID == False:
  148. timeID = str(round(time.time() * 1000000))
  149. ID = userPhone + timeID
  150. return ID
  151. else:
  152. timeID = str(round(time.time() * 1000000))
  153. eID = '13800' + timeID + '138000'
  154. return eID
  155. else:
  156. if getUser == True:
  157. timeID = str(round(time.time() * 1000))
  158. userID = timeID + userPhone
  159. return userID
  160. else:
  161. if setOTAID == False:
  162. timeID = str(round(time.time() * 1000))
  163. ID = userPhone + timeID
  164. return ID
  165. else:
  166. timeID = str(round(time.time() * 1000))
  167. eID = '13800' + timeID + '138000'
  168. return eID
  169. @staticmethod
  170. def get_username(userID):
  171. """
  172. 根据用户id获取用户名/邮箱/电话
  173. @param userID: 用户id
  174. @return:
  175. """
  176. if userID:
  177. device_user_qs = Device_User.objects.filter(userID=userID).values('username', 'userEmail', 'phone')
  178. if device_user_qs.exists():
  179. if device_user_qs[0]['username']:
  180. return device_user_qs[0]['username']
  181. elif device_user_qs[0]['userEmail']:
  182. return device_user_qs[0]['userEmail']
  183. elif device_user_qs[0]['phone']:
  184. return device_user_qs[0]['phone']
  185. return ''
  186. # 生成随机数
  187. @staticmethod
  188. def RandomStr(randomlength=8, number=True):
  189. str = ''
  190. if number == False:
  191. characterSet = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsT' \
  192. 'tUuVvWwXxYyZz0123456789'
  193. else:
  194. characterSet = '0123456789'
  195. length = len(characterSet) - 1
  196. random = Random()
  197. for index in range(randomlength):
  198. str += characterSet[random.randint(0, length)]
  199. return str
  200. # 生成订单好
  201. @staticmethod
  202. def createOrderID():
  203. random_id = CommonService.RandomStr(6, True)
  204. order_id = datetime.datetime.now().strftime('%Y%m%d%H%M%S') + str(random_id)
  205. print('orderID:')
  206. print(order_id)
  207. return order_id
  208. # qs转换list datetime处理
  209. @staticmethod
  210. def qs_to_list(qs):
  211. res = []
  212. # print(qs)
  213. for ps in qs:
  214. try:
  215. if 'time' in ps:
  216. ps['time'] = ps['time'].strftime("%Y-%m-%d %H:%M:%S")
  217. if 'add_time' in ps:
  218. ps['add_time'] = ps['add_time'].strftime("%Y-%m-%d %H:%M:%S")
  219. if 'update_time' in ps:
  220. ps['update_time'] = ps['update_time'].strftime("%Y-%m-%d %H:%M:%S")
  221. if 'end_time' in ps:
  222. ps['end_time'] = ps['end_time'].strftime("%Y-%m-%d %H:%M:%S")
  223. if 'data_joined' in ps:
  224. if ps['data_joined']:
  225. ps['data_joined'] = ps['data_joined'].strftime("%Y-%m-%d %H:%M:%S")
  226. else:
  227. ps['data_joined'] = ''
  228. if 'userID__data_joined' in ps:
  229. if ps['userID__data_joined']:
  230. ps['userID__data_joined'] = ps['userID__data_joined'].strftime("%Y-%m-%d %H:%M:%S")
  231. else:
  232. ps['userID__data_joined'] = ''
  233. except Exception as e:
  234. pass
  235. res.append(ps)
  236. return res
  237. # 获取当前时间
  238. @staticmethod
  239. def get_now_time_str(n_time, tz, lang):
  240. print(n_time)
  241. print(tz)
  242. print(lang)
  243. n_time = int(n_time) + 3600 * float(tz)
  244. if lang == 'cn':
  245. return time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(int(n_time)))
  246. else:
  247. return time.strftime('%m-%d-%Y %H:%M:%S', time.gmtime(int(n_time)))
  248. # 生成随机数
  249. @staticmethod
  250. def encrypt_data(randomlength=8, number=False):
  251. str = ''
  252. if number == False:
  253. characterSet = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsT' \
  254. 'tUuVvWwXxYyZz0123456789'
  255. else:
  256. characterSet = '0123456789'
  257. length = len(characterSet) - 1
  258. random = Random()
  259. for index in range(randomlength):
  260. str += characterSet[random.randint(0, length)]
  261. return str
  262. @staticmethod
  263. def encode_data(content, start=1, end=4):
  264. """
  265. 数据加密
  266. @param content: 数据内容
  267. @param start: 起始长度
  268. @param end: 结束长度
  269. @return content: 加密的数据
  270. """
  271. if not content:
  272. return ''
  273. for i in range(start, end):
  274. length = end - i
  275. content = RandomStr(length, False) + content + RandomStr(length, False)
  276. content = base64.b64encode(str(content).encode('utf-8')).decode('utf8')
  277. return content
  278. @staticmethod
  279. def decode_data(content, start=1, end=4):
  280. """
  281. 数据解密
  282. @param content: 数据内容
  283. @param start: 起始长度
  284. @param end: 结束长度
  285. @return content: 解密的数据
  286. """
  287. if not content:
  288. return ''
  289. for i in range(start, end):
  290. content = base64.b64decode(content)
  291. content = content.decode('utf-8')
  292. content = content[i:-i]
  293. return content
  294. # 把格式化时间转换成时间戳
  295. @staticmethod
  296. def str_to_timestamp(str_time=None, format='%Y-%m-%d %H:%M:%S'):
  297. if str_time:
  298. time_tuple = time.strptime(str_time, format) # 把格式化好的时间转换成元祖
  299. result = time.mktime(time_tuple) # 把时间元祖转换成时间戳
  300. return int(result)
  301. return int(time.time())
  302. # 把时间戳转换成格式化
  303. @staticmethod
  304. def timestamp_to_str(timestamp=None, format='%Y-%m-%d %H:%M:%S'):
  305. if timestamp:
  306. time_tuple = time.localtime(timestamp) # 把时间戳转换成时间元祖
  307. result = time.strftime(format, time_tuple) # 把时间元祖转换成格式化好的时间
  308. return result
  309. else:
  310. return time.strptime(format)
  311. @staticmethod
  312. def get_date_from_timestamp(timestamp, timezone_offset):
  313. # 创建时区对象
  314. tz = datetime.timezone(datetime.timedelta(hours=timezone_offset))
  315. # 使用时间戳创建 datetime 对象
  316. dt = datetime.datetime.fromtimestamp(timestamp, tz)
  317. # 格式化成 '%Y-%m-%d'
  318. formatted_date = dt.strftime('%Y-%m-%d %H:%M:%S')
  319. return formatted_date
  320. # 计算N个月后的时间戳
  321. @staticmethod
  322. def calcMonthLater(addMonth, unix_timestamp=None):
  323. if unix_timestamp:
  324. now_year = time.localtime(unix_timestamp).tm_year
  325. now_month = time.localtime(unix_timestamp).tm_mon
  326. now_day = time.localtime(unix_timestamp).tm_mday
  327. now_hour = time.localtime(unix_timestamp).tm_hour
  328. now_min = time.localtime(unix_timestamp).tm_min
  329. now_second = time.localtime(unix_timestamp).tm_sec
  330. else:
  331. now_year = datetime.datetime.now().year
  332. now_month = datetime.datetime.now().month
  333. now_day = datetime.datetime.now().day
  334. now_hour = datetime.datetime.now().hour
  335. now_min = datetime.datetime.now().minute
  336. now_second = datetime.datetime.now().second
  337. for add in range(addMonth):
  338. if now_month == 12:
  339. now_year += 1
  340. now_month = 1
  341. else:
  342. now_month += 1
  343. timestamps = 0
  344. for is_format in range(4):
  345. try:
  346. date_format = '{now_year}-{now_month}-{now_day} {now_hour}:{now_min}:{now_second}' \
  347. .format(now_year=now_year, now_month=now_month, now_day=now_day, now_hour=now_hour,
  348. now_min=now_min, now_second=now_second)
  349. timestamps = CommonService.str_to_timestamp(date_format)
  350. except Exception as e:
  351. if str(e) == 'day is out of range for month':
  352. now_day = now_day - 1
  353. return timestamps
  354. @staticmethod
  355. def updateMac(mac: str):
  356. macArray = mac.split(':')
  357. macArray[0] = int(macArray[0], 16)
  358. macArray[1] = int(macArray[1], 16)
  359. macArray[2] = int(macArray[2], 16)
  360. first = int(macArray[5], 16)
  361. second = int(macArray[4], 16)
  362. three = int(macArray[3], 16)
  363. if first == 255 and second == 255 and three == 255:
  364. return None
  365. first += 1
  366. if first / 256 == 1:
  367. second += 1
  368. first = first % 256
  369. if second / 256 == 1:
  370. three += 1
  371. second = second % 256
  372. macArray[3] = three
  373. macArray[4] = second
  374. macArray[5] = first
  375. tmp = ':'.join(map(lambda x: "%02x" % x, macArray))
  376. return tmp.upper()
  377. @staticmethod
  378. def encode_data_without_salt(content):
  379. return base64.b64encode(str(content).encode("utf-8")).decode('utf8')
  380. @staticmethod
  381. def check_time_stamp_token(token, time_stamp):
  382. # 时间戳token校验
  383. if not all([token, time_stamp]):
  384. return False
  385. try:
  386. token = int(CommonService.decode_data(token))
  387. time_stamp = int(time_stamp)
  388. now_time = int(time.time())
  389. distance = now_time - time_stamp
  390. if token != time_stamp or distance > 60000 or distance < -60000: # 为了全球化时间控制在一天内
  391. return False
  392. return True
  393. except Exception as e:
  394. print(e)
  395. return False
  396. @staticmethod
  397. def check_time_stamp_token_without_distance(time_stamp_token, time_stamp):
  398. """
  399. 用于没有RTC设备的时间戳token校验
  400. @param time_stamp: 时间戳
  401. @param time_stamp_token: 时间戳token
  402. @return: boolean True/False
  403. """
  404. if not all([time_stamp_token, time_stamp]):
  405. return False
  406. try:
  407. token = CommonService.decode_data(time_stamp_token)
  408. if token != time_stamp:
  409. return False
  410. return True
  411. except Exception as e:
  412. print(e)
  413. return False
  414. @staticmethod
  415. def req_publish_mqtt_msg(identification_code, topic_name, msg, qos=1):
  416. """
  417. 通用发布MQTT消息函数
  418. @param identification_code: 标识码
  419. @param topic_name: 主题名
  420. @param msg: 消息内容
  421. @param qos: mqtt qos等级
  422. @return: boolean
  423. """
  424. if not all([identification_code, topic_name]):
  425. return False
  426. if identification_code.endswith('11L'):
  427. thing_name = 'LC_' + identification_code
  428. else:
  429. thing_name = 'Ansjer_Device_' + identification_code
  430. try:
  431. # 获取数据组织将要请求的url
  432. iot = iotdeviceInfoModel.objects.filter(
  433. thing_name=thing_name).values(
  434. 'endpoint', 'token_iot_number')
  435. if not iot.exists():
  436. return False
  437. endpoint = iot[0]['endpoint']
  438. Token = iot[0]['token_iot_number']
  439. # api doc: https://docs.aws.amazon.com/zh_cn/iot/latest/developerguide/http.html
  440. # url: https://IoT_data_endpoint/topics/url_encoded_topic_name?qos=1
  441. # post请求url发布MQTT消息
  442. url = 'https://{}/topics/{}?qos={}'.format(endpoint, topic_name, qos)
  443. authorizer_name = 'Ansjer_Iot_Auth'
  444. signature = CommonService.rsa_sign(Token) # Token签名
  445. headers = {
  446. 'x-amz-customauthorizer-name': authorizer_name,
  447. 'Token': Token,
  448. 'x-amz-customauthorizer-signature': signature}
  449. r = requests.post(url=url, headers=headers, json=msg, timeout=2)
  450. if r.status_code == 200:
  451. res = r.json()
  452. if res['message'] == 'OK':
  453. return True
  454. return False
  455. else:
  456. return False
  457. except Exception as e:
  458. return False
  459. @staticmethod
  460. def rsa_sign(Token):
  461. # 私钥签名Token
  462. if not Token:
  463. return ''
  464. private_key_file = '''-----BEGIN RSA PRIVATE KEY-----
  465. MIIEpQIBAAKCAQEA5iJzEDPqtGmFMggekVro6C0lrjuC2BjunGkrFNJWpDYzxCzE
  466. X5jf4/Fq7hcIaQd5sqHugDxPVollSLPe9zNilbrd0sZfU+Ed8gRVuKW9KwfE9XFr
  467. L0pt6bKRQ0IIRfiZ9TuR0tsQysvcO1GZSXcYfPue3tGM1zOnWFThWDqZ06+sOxzt
  468. RMRl4yNfbpCG4MfxG3itNXOfrjZv2OMLSXrxmzubSvRpUYSvQPs4fm9302SAnySY
  469. 0MKzx6H6528ZQm/IDDSZy6EmNBIyTRDfxC56vnYcXvqedAQh7jJnjdvt6Q4MhASH
  470. eIYi1FBSdu2NT6wgpnrqXzx5pq9kR/lnsLID0wIDAQABAoIBAQCiF4GT1/1oNSpr
  471. ouxk1PNXFPWFUsVGD8mAwVJmx//eiY7MjfuCmdqYYmI+cFqsH2fIOeYSzGfVO9Dq
  472. 9EYHN1oovAWhf7eFDPpajFMUSyiCNmazub8VAAeKowtNpCTPo9pMsDh1m3aoYA4u
  473. ebrN0+Sbo16y8kWRDgDAZoiR7DSMs8lczk16hwfv5mw8XpNDbaL3Coi4Koe2S1Yh
  474. 2SX3vWFlpd7qF1ZYXuZIp+b8JPrV7n9eUKoFgzj0gqgwQK80CoexIjiOrNMPvkQa
  475. q+8kCvFjAzKxOK7e8gjM8lMRiGodb61kmYZkkJzFwWO4EaGbl34lfVECd1Ixp3tF
  476. be0OWAGBAoGBAPSteXDzzToD8ovM7LL11x0jWwI6HOiHu89kZtW566rIezjWBuA2
  477. TxrcYKM3h9jQRXS3CsMdoIv6XGk5lqM8ADtjn23FBWe/THYLh8bm8JOgh5RRWQDg
  478. SvkLfi9Ih2mM4NJfmuuDOh3Nze2efLM7+kOZWUQwF2Zx9mL5jvRBk351AoGBAPDI
  479. sYmT2Li+i5+0vykA2m5uPF8ZOW8BGtAfCZv0suW7BNzSgin78g9WapRd/4p0NNiL
  480. /nVMqPPCpd1akCUpV+GDWQt0hV+HZjxANE0KWhciQRyo2qvo51j8SWILJSgh0tXC
  481. aTF8qt6oGw3VN3m57vKhbrlDaz0J/NDJFci6msAnAoGBAOuG6bXPGijUj+//DYKf
  482. n7jOxdZ49kboEePrtAncdHzri6IEdI3z+WXT6bpzw/LzWUimwldb96WHFNm9s8Hi
  483. Ch8hIODbnP5naUTgiIzw1XhmONyPCewL/F+LrqX5XVA/alNX8JrwsUrrR2WLAGLQ
  484. Q3I69XDsEjptTU2tCO0bCs3ZAoGBAJ2lCHfm0JHET230zONvp5N9oREyVqQSuRdh
  485. +syc3TQDyh85w/bw+X6JOaaCFHj1tFPC9Iqf8k4GNspCLPXnp54CfR4+38O3xnvU
  486. HWoDSRC0YKT++IxtJGriYrlKSr2Hx54kdvLriIPW1D+uRW/xCDza7L9nIKMKEvgv
  487. b4/IfOEpAoGAeKM9Te7T1VzlAkS0CJOwanzwYV/zrex84WuXxlsGgPQ871lTs5AP
  488. H1QLfLfFXH+UVrCEC2yv4eml/cqFkpB3gE5i4MQ8GPVIOSs5tsIyl8YUA03vdNdB
  489. GCqvlyw5dfxNA+EtxNE2wCW/LW7ENJlACgcfgPlBZtpLheWoZB/maw4=
  490. -----END RSA PRIVATE KEY-----'''
  491. # 使用密钥文件方式
  492. # private_key_file_path = os.path.join(BASE_DIR, 'static/iotCore/private.pem')#.replace('\\', '/')
  493. # private_key_file = open(private_key_file_path, 'r')
  494. private_key = ct.load_privatekey(ct.FILETYPE_PEM, private_key_file)
  495. signature = ct.sign(private_key, Token.encode('utf8'), 'sha256')
  496. signature = encodebytes(signature).decode('utf8').replace('\n', '')
  497. # print('signature:', signature)
  498. return signature
  499. @staticmethod
  500. def get_payment_status_url(lang, payment_status):
  501. # 返回相应的支付状态url
  502. if lang == 'cn':
  503. file_name = 'success.html' if payment_status == 'success' else 'fail.html'
  504. else:
  505. file_name = 'en_success.html' if payment_status == 'success' else 'en_fail.html'
  506. pay_failed_url = "{}web/paid2/{}".format(SERVER_DOMAIN_SSL, file_name)
  507. return pay_failed_url
  508. # 根据uid查询序列号,存在则返回序列号,否则返uid
  509. @staticmethod
  510. def query_serial_with_uid(uid):
  511. device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number')
  512. if device_info_qs.exists():
  513. serial_number = device_info_qs[0]['serial_number']
  514. if serial_number:
  515. return serial_number
  516. return uid
  517. # 根据序列号查询uid,存在则返回uid,否则返回序列号
  518. @staticmethod
  519. def query_uid_with_serial(serial_number):
  520. device_info_qs = Device_Info.objects.filter(serial_number=serial_number).values('UID')
  521. if device_info_qs.exists():
  522. uid = device_info_qs[0]['UID']
  523. if uid:
  524. return uid
  525. return serial_number
  526. @staticmethod
  527. def get_full_serial_number(uid, serial_number, device_type):
  528. """
  529. 根据uid查询返回完整序列号
  530. @param uid: uid
  531. @param serial_number: 9位序列号
  532. @param device_type: 设备类型
  533. @return: full_serial_number
  534. """
  535. p2p_type = str(UIDModel.objects.filter(uid=uid).values('p2p_type')[0]['p2p_type'])
  536. # 设备类型转为16进制并补齐4位
  537. device_type = hex(device_type)[2:]
  538. device_type = (4 - len(device_type)) * '0' + device_type
  539. full_serial_number = serial_number + p2p_type + device_type
  540. return full_serial_number
  541. # 根据企业标识返回物品名
  542. @staticmethod
  543. def get_thing_name(company_mark, thing_name_suffix):
  544. if company_mark == '11A':
  545. return 'Ansjer_Device_' + thing_name_suffix
  546. elif company_mark == '11L':
  547. return 'LC_' + thing_name_suffix
  548. else:
  549. return thing_name_suffix
  550. @staticmethod
  551. def confirm_region_id(region_country=0):
  552. """
  553. 根据配置信息和国家确定region_id
  554. @param region_country: 用户国家id
  555. @return: region_id
  556. """
  557. # region_id 为 tb_region 表的id,根据数据库的数据决定编码
  558. region_id = 3
  559. if CONFIG_INFO == CONFIG_US: # 美洲
  560. # 中东地区国家id
  561. if region_country in ME_COUNTRY_ID_LIST:
  562. region_id = 6
  563. # 东亚地区国家id
  564. elif region_country in EA_COUNTRY_ID_LIST:
  565. region_id = 2
  566. elif CONFIG_INFO == CONFIG_EUR: # 欧洲
  567. # 俄罗斯
  568. if region_country in RU_COUNTRY_ID_LIST:
  569. region_id = 6
  570. else:
  571. region_id = 4
  572. elif CONFIG_INFO == CONFIG_CN: # 中国
  573. region_id = 1
  574. elif CONFIG_INFO == CONFIG_TEST: # 测试
  575. region_id = 5
  576. return region_id
  577. @staticmethod
  578. def verify_token_get_user_id(request_dict, request):
  579. """
  580. 认证token,获取user id
  581. @param request_dict: 请求参数
  582. @param request: 请求体
  583. @return: token_obj.code, token_obj.userID, response
  584. """
  585. try:
  586. token_obj = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
  587. lang = request_dict.get('lang', None)
  588. response = ResponseObject(lang if lang else token_obj.lang)
  589. return token_obj.code, token_obj.userID, response
  590. except Exception as e:
  591. print(e)
  592. return 309, None, None
  593. @staticmethod
  594. def cutting_time(start_time, end_time, time_unit):
  595. """
  596. 按时间单位切割时间段
  597. @param start_time: 开始时间
  598. @param end_time: 结束时间
  599. @param time_unit: 时间单位
  600. @return: time_list 切割后的时间列表
  601. """
  602. time_list = []
  603. while True:
  604. if time_unit == 'day':
  605. temp_time = start_time + relativedelta(days=1)
  606. elif time_unit == 'week':
  607. temp_time = start_time + relativedelta(days=7)
  608. elif time_unit == 'month':
  609. temp_time = start_time + relativedelta(months=1)
  610. elif time_unit == 'quarter':
  611. temp_time = start_time + relativedelta(months=3)
  612. elif time_unit == 'year':
  613. temp_time = start_time + relativedelta(years=1)
  614. else:
  615. break
  616. if temp_time < end_time:
  617. time_tuple = (CommonService.str_to_timestamp(start_time.strftime('%Y-%m-%d %H:%M:%S')),
  618. CommonService.str_to_timestamp(temp_time.strftime('%Y-%m-%d %H:%M:%S')))
  619. time_list.append(time_tuple)
  620. start_time = temp_time
  621. else:
  622. time_tuple = (CommonService.str_to_timestamp(start_time.strftime('%Y-%m-%d %H:%M:%S')),
  623. CommonService.str_to_timestamp(end_time.strftime('%Y-%m-%d %H:%M:%S')))
  624. if time_tuple not in time_list:
  625. time_list.append(time_tuple)
  626. break
  627. if not time_list:
  628. time_tuple = (CommonService.str_to_timestamp(start_time.strftime('%Y-%m-%d %H:%M:%S')),
  629. CommonService.str_to_timestamp(end_time.strftime('%Y-%m-%d %H:%M:%S')))
  630. time_list = [time_tuple]
  631. return time_list
  632. @staticmethod
  633. def cutting_time_stamp(start_time, end_time):
  634. """
  635. 按天切割时间段
  636. @param start_time: 开始时间
  637. @param end_time: 结束时间
  638. @return: time_list 切割后的时间列表
  639. """
  640. time_list = []
  641. while True:
  642. mid_time = datetime.datetime(start_time.year, start_time.month, start_time.day) + relativedelta(days=1)
  643. if mid_time < end_time:
  644. time_tuple = (CommonService.str_to_timestamp(start_time.strftime('%Y-%m-%d %H:%M:%S')),
  645. CommonService.str_to_timestamp(mid_time.strftime('%Y-%m-%d %H:%M:%S')))
  646. time_list.append(time_tuple)
  647. start_time = mid_time
  648. else:
  649. time_tuple = (CommonService.str_to_timestamp(start_time.strftime('%Y-%m-%d %H:%M:%S')),
  650. CommonService.str_to_timestamp(end_time.strftime('%Y-%m-%d %H:%M:%S')))
  651. if time_tuple not in time_list:
  652. time_list.append(time_tuple)
  653. break
  654. if not time_list:
  655. time_tuple = (CommonService.str_to_timestamp(start_time.strftime('%Y-%m-%d %H:%M:%S')),
  656. CommonService.str_to_timestamp(end_time.strftime('%Y-%m-%d %H:%M:%S')))
  657. time_list = [time_tuple]
  658. return time_list
  659. @staticmethod
  660. def get_domain_name():
  661. """
  662. 获取域名
  663. @return: domain_name_list 域名列表
  664. """
  665. if CONFIG_INFO == CONFIG_TEST:
  666. domain_name_list = [SERVER_DOMAIN_TEST[:-1]]
  667. elif CONFIG_INFO == CONFIG_CN or CONFIG_INFO == CONFIG_US or CONFIG_INFO == CONFIG_EUR:
  668. domain_name_list = [SERVER_DOMAIN_US[:-1], SERVER_DOMAIN_CN[:-1], SERVER_DOMAIN_EUR[:-1]]
  669. else:
  670. domain_name_list = []
  671. return domain_name_list
  672. @staticmethod
  673. def get_orders_domain_name_list():
  674. """
  675. 获取其他服务器域名列表
  676. @return: orders_domain_name_list 其他服务器域名列表
  677. """
  678. orders_domain_name_list = SERVER_DOMAIN_LIST
  679. if CONFIG_INFO == CONFIG_TEST:
  680. orders_domain_name_list = [SERVER_DOMAIN_CN, SERVER_DOMAIN_US, SERVER_DOMAIN_EUR]
  681. elif CONFIG_INFO == CONFIG_CN:
  682. orders_domain_name_list = [SERVER_DOMAIN_TEST, SERVER_DOMAIN_US, SERVER_DOMAIN_EUR]
  683. elif CONFIG_INFO == CONFIG_US:
  684. orders_domain_name_list = [SERVER_DOMAIN_TEST, SERVER_DOMAIN_CN, SERVER_DOMAIN_EUR]
  685. elif CONFIG_INFO == CONFIG_EUR:
  686. orders_domain_name_list = [SERVER_DOMAIN_TEST, SERVER_DOMAIN_CN, SERVER_DOMAIN_US]
  687. return orders_domain_name_list
  688. @staticmethod
  689. def list_sort(e):
  690. """
  691. 列表排序
  692. @param e: 列表元素
  693. """
  694. return sorted(e, key=lambda item: -item['count'])
  695. @staticmethod
  696. def list_sort_v2(e, order_by):
  697. """
  698. 列表排序
  699. @param e: 列表元素
  700. @param order_by: 排序对象
  701. """
  702. return sorted(e, key=lambda item: item[order_by], reverse=True)
  703. @staticmethod
  704. def Package_Type(order_type, content):
  705. """
  706. 套餐类型
  707. """
  708. if order_type == 0:
  709. content = content + '(' + '云存' + ')'
  710. return content
  711. elif order_type == 1:
  712. content = content + '(' + 'AI' + ')'
  713. return content
  714. elif order_type == 2:
  715. pass
  716. elif order_type == 4:
  717. content = content + '(' + '云盘' + ')'
  718. return content
  719. @staticmethod
  720. def is_cloud_device(ucode, device_type):
  721. """
  722. 设备是否支持云存
  723. @param ucode: 设备版本
  724. @param device_type: 设备类型
  725. """
  726. if len(ucode) > 4:
  727. number = ucode[-4]
  728. else:
  729. return False
  730. device_type_qs = AppDeviceType.objects.filter(type=device_type).values('model')
  731. model = device_type_qs[0]['model'] if device_type_qs.exists() else ''
  732. # 判断设备是否为ipc设备和是否支持云存
  733. if model == 2 and number in ['4', '5']:
  734. return True
  735. return False
  736. @staticmethod
  737. def negative_number_judgment(number_list):
  738. """
  739. 判断正负数
  740. @param number_list: float或int类型列表
  741. """
  742. if any(i < 0 for i in number_list):
  743. return False
  744. else:
  745. return True
  746. @staticmethod
  747. def check_password(password1, password2):
  748. """
  749. 比较密码
  750. @param 返回True or False
  751. """
  752. return constant_time_compare(password1, password2)
  753. @staticmethod
  754. def compare_version_number(version_number, version_number_list):
  755. """
  756. 比对版本号大小
  757. @param version_number: 版本号
  758. @param version_number_list: 版本号列表
  759. """
  760. version_list = []
  761. input_version = LooseVersion(version_number)
  762. for version in version_number_list:
  763. version = LooseVersion(version)
  764. if input_version >= version:
  765. version_list.append(version)
  766. else:
  767. continue
  768. return version_list
  769. @staticmethod
  770. def convert_to_timestamp(timezone_offset, time_string):
  771. """
  772. 时间字符串转为时间戳
  773. @param timezone_offset: 时区
  774. @param time_string: 时间字符串
  775. @return: timestamp
  776. """
  777. datetime_obj = datetime.datetime.strptime(time_string, '%Y-%m-%d %H:%M:%S')
  778. # 创建一个表示指定时区的timedelta对象
  779. utc_offset = datetime.timedelta(hours=timezone_offset)
  780. # 调整时区
  781. datetime_obj = datetime_obj - utc_offset
  782. # datetime.datetime对象 -> str
  783. time_str_utc = datetime_obj.strftime("%Y-%m-%d %H:%M:%S")
  784. timestamp = calendar.timegm(time.strptime(time_str_utc, '%Y-%m-%d %H:%M:%S'))
  785. return timestamp
  786. @staticmethod
  787. def get_uid_by_serial_number(serial_number):
  788. """
  789. 根据序列号获取绑定uid
  790. @param serial_number: 9位序列号
  791. @return: uid信息
  792. """
  793. c_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__serial_number=serial_number[0:6])
  794. if not c_serial_qs.exists():
  795. return serial_number
  796. c_serial_info = c_serial_qs.values('uid__uid')
  797. return c_serial_info[0]['uid__uid']
  798. @staticmethod
  799. def get_uids_by_serial_numbers(serial_numbers):
  800. """
  801. 根据多个序列号获取绑定uid列表
  802. @param serial_numbers: 多个6位序列号列表
  803. @return: uid列表
  804. """
  805. if not serial_numbers:
  806. return []
  807. # 确保所有序列号都是6位
  808. serial_list = [serial[:6] for serial in serial_numbers if serial]
  809. if not serial_list:
  810. return []
  811. # 查询所有匹配的序列号
  812. c_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__serial_number__in=serial_list)
  813. # 如果没有匹配记录,返回原序列号列表
  814. if not c_serial_qs.exists():
  815. return serial_numbers
  816. # 获取所有匹配的uid
  817. uid_list = list(c_serial_qs.values_list('uid__uid', flat=True))
  818. return uid_list
  819. @staticmethod
  820. def get_serial_number_by_uid(uid):
  821. """
  822. 根据序列号获取绑定uid
  823. @param uid: uid
  824. @return: uid信息
  825. """
  826. c_serial_qs = UIDCompanySerialModel.objects.filter(uid__uid=uid)
  827. if not c_serial_qs.exists():
  828. return uid
  829. c_serial_qs = c_serial_qs.annotate(mark=F('company_serial__company__mark'),
  830. serial_number=F('company_serial__serial_number'))
  831. c_serial_info = c_serial_qs.values('mark', 'serial_number')
  832. return c_serial_info[0]['serial_number'] + c_serial_info[0]['mark']
  833. @staticmethod
  834. def get_user_tz(user_id):
  835. """
  836. 获取用户时区
  837. @param user_id: 用户id
  838. @return: tz
  839. """
  840. # 从gateway_push表查询时区
  841. gateway_push_qs = GatewayPush.objects.filter(user_id=user_id).order_by('-id').first()
  842. if gateway_push_qs is None:
  843. tz = 0.00
  844. else:
  845. # 截掉.00然后转为浮点型
  846. tz = float(gateway_push_qs.tz[:-3])
  847. return tz
  848. @staticmethod
  849. def update_alexa_events(data_list):
  850. """
  851. 请求Alexa服务器更新事件网关
  852. 邮件提醒捕获的异常
  853. @param data_list: 数据列表
  854. @return:
  855. """
  856. try:
  857. data_list = json.dumps(data_list)
  858. data = {'data_list': data_list}
  859. url = ALEXA_DOMAIN + 'deviceStatus/addOrUpdateV2'
  860. requests.post(url, data=data, timeout=30)
  861. except Exception as e:
  862. S3Email().faEmail(
  863. '请求Alexa服务器更新事件网关异常:error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)),
  864. 'servers@ansjer.com')
  865. pass
  866. @classmethod
  867. def confirm_msg_sign_name(cls, sign_name, phone):
  868. """
  869. 确认短信签名
  870. @param sign_name: app签名标识
  871. @param phone: 手机号
  872. @return:
  873. """
  874. if sign_name == 'zosi':
  875. sign_name = '周视'
  876. elif sign_name == 'vsees':
  877. # 微瞳移动号码使用 Ansjer 签名
  878. is_china_mobile = cls.is_china_mobile(phone)
  879. if is_china_mobile:
  880. sign_name = 'Ansjer'
  881. else:
  882. sign_name = '微瞳'
  883. else:
  884. sign_name = 'Ansjer'
  885. return sign_name
  886. @staticmethod
  887. def is_china_mobile(phone):
  888. """
  889. 检查手机号码是否属于中国移动
  890. :param phone: 手机号码字符串(11位数字)
  891. :return: 如果是移动号码返回True,否则False
  892. """
  893. # 正则表达式匹配中国移动号段
  894. pattern = r'^1(3[4-9]|4[7]|5[0-27-9]|7[28]|8[2-47-8]|9[58])\d{8}$'
  895. return bool(re.fullmatch(pattern, phone))
  896. @staticmethod
  897. def confirm_msg_sign_name_with_phone(phone):
  898. """
  899. 根据手机号确认短信签名
  900. @param phone: 手机号码
  901. @return:
  902. """
  903. sign_name = '周视'
  904. # 根据用户APP包名确定短信签名
  905. device_user_qs = Device_User.objects.filter(username=phone).values('userID')
  906. if device_user_qs.exists():
  907. user_id = device_user_qs[0]['userID']
  908. user_ex_qs = UserExModel.objects.filter(userID=user_id).values('appBundleId')
  909. if user_ex_qs.exists():
  910. if user_ex_qs[0]['appBundleId'] in ['com.cloudlife.commissionf', 'com.cloudlife.commissionf_a']:
  911. sign_name = '微瞳'
  912. return sign_name