utils.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. # -*- coding: utf-8 -*-
  2. #!/usr/bin/env python
  3. import calendar
  4. import datetime
  5. import math
  6. import numbers
  7. from typing import TYPE_CHECKING, Optional
  8. from django.conf import settings
  9. from pandas import date_range
  10. from apps.web.constant import Const
  11. if TYPE_CHECKING:
  12. from apps.web.device.models import DeviceDict
  13. from apps.web.dealer.models import Dealer
  14. class CoordinateTrans(object):
  15. """
  16. 坐标系转换
  17. """
  18. def __init__(self, lng=0.0, lat=0.0):
  19. """
  20. :param lng: 经度
  21. :param lat: 维度
  22. """
  23. self._x_pi = 3.14159265358979324 * 3000.0 / 180.0
  24. self._lng = lng
  25. self._lat = lat
  26. def bd09_to_gcj02(self):
  27. """
  28. 百度坐标系到google坐标系的经纬度转换
  29. :return:
  30. """
  31. if self._lng == 0.0 or self._lat == 0.0:
  32. return self._lng, self._lat
  33. x = self._lng - 0.0065
  34. y = self._lat - 0.006
  35. z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * self._x_pi)
  36. theta = math.atan2(y, x) - 0.000003 * math.cos(x * self._x_pi)
  37. gg_lng = z * math.cos(theta)
  38. gg_lat = z * math.sin(theta)
  39. return [gg_lng, gg_lat]
  40. def gcj02_to_bd09(self):
  41. """
  42. 高德/谷歌 坐标系 转百度
  43. :return:
  44. """
  45. if self._lng == 0.0 or self._lat == 0.0:
  46. return self._lng, self._lat
  47. z = math.sqrt(self._lng * self._lng + self._lat * self._lat) + 0.00002 * math.sin(self._lat * self._x_pi)
  48. theta = math.atan2(self._lat, self._lng) + 0.000003 * math.cos(self._lng * self._x_pi)
  49. bd_lng = z * math.cos(theta) + 0.0065
  50. bd_lat = z * math.sin(theta) + 0.006
  51. return [bd_lng, bd_lat]
  52. def __call__(self, lng, lat, _type="b_to_g"):
  53. """
  54. :param lng:
  55. :param lat:
  56. :param _type: b_to_g 百度转高德 g_to_b 高德转百度
  57. :return:
  58. """
  59. self._lng = lng
  60. self._lat = lat
  61. if _type == "b_to_g":
  62. return self.bd09_to_gcj02()
  63. elif _type == "g_to_b":
  64. return self.gcj02_to_bd09()
  65. else:
  66. pass
  67. class IntToHex(object):
  68. """
  69. 数字转换16进制字符串
  70. """
  71. def __init__(self):
  72. self._number = None
  73. def _add_trans_number(self, number):
  74. if isinstance(number, numbers.Integral):
  75. self._number = number
  76. elif isinstance(number, str) and number.isdigit():
  77. self._number = int(number)
  78. else:
  79. raise TypeError("type of number must in <Integral,str>")
  80. @staticmethod
  81. def _reverse_hex(h):
  82. if not len(h):
  83. return ""
  84. return h[-2:] + IntToHex._reverse_hex(h[:-2])
  85. def __call__(self, number, lens=4, reverse=False): # type:(Optional[numbers.Integral, str], int, bool) -> str
  86. if not isinstance(lens, numbers.Integral):
  87. raise TypeError("type of lens must be Integral")
  88. self._add_trans_number(number)
  89. formatStr = "{:0>%sX}" % lens
  90. numberHex = formatStr.format(self._number)
  91. if reverse:
  92. return IntToHex._reverse_hex(numberHex)
  93. return numberHex
  94. class DealerGetPackages(object):
  95. def __init__(self, device, visitor, isTemp=False): # type: (DeviceDict, Dealer, bool) -> None
  96. self._device = device
  97. self._visitor = visitor
  98. self._isTemp = isTemp
  99. @property
  100. def unitPrice(self):
  101. return self._device.otherConf.get("unit_price", "")
  102. @property
  103. def devData(self): # type: ()-> dict
  104. """
  105. 设备数据
  106. """
  107. if not self._device.is_registered:
  108. return {
  109. "id": self._device.devNo,
  110. "maxCoins": self._device.otherConf.get("maxCoins", 4),
  111. "devNo": self._device.devNo,
  112. "type": u"脉冲",
  113. "typeCode": u"201",
  114. "groupName": u"测试",
  115. "groupNumber": 666,
  116. }
  117. devData = {
  118. "id": self._device.devNo,
  119. "maxCoins": self._device.otherConf.get("maxCoins", 4),
  120. "devNo": self._device.devNo,
  121. "type": self._device.devTypeName,
  122. "typeCode": self._device.devTypeCode,
  123. "groupName": self._device.group.groupName,
  124. "groupNumber": self._device.groupNumber
  125. }
  126. if self._device.devTypeCode in [Const.DEVICE_TYPE_CODE_HP_GATE]:
  127. chargeIndex = {}
  128. if self._device.otherConf.get("controlEnter") in ("1", "2"):
  129. chargeIndex["enter"] = "idle"
  130. if self._device.otherConf.get("controlExit") in ("1", "2"):
  131. chargeIndex["exit"] = "idle"
  132. devData.update({"chargeIndex": chargeIndex})
  133. return devData
  134. @property
  135. def ruleList(self): # type: () -> list
  136. """
  137. 套餐列表
  138. """
  139. # 此处可以将套餐抽象化表达
  140. if not self._device.is_registered:
  141. rules = [
  142. {"id": "".format(i), "name": u"测试", "coins": i, "price": i}
  143. for i in range(1, 6)
  144. ]
  145. else:
  146. rules = []
  147. return rules
  148. coordinateHandler = CoordinateTrans()
  149. int_to_hex = IntToHex()
  150. def get_start_and_end_by_month(monthStr):
  151. # type:(str) -> (str, str)
  152. """根据月份获取 当月月初和月末"""
  153. year, month = map(lambda x: int(x), monthStr.split("-"))
  154. firstWeekDay, lastDay = calendar.monthrange(year, month)
  155. startTime = datetime.date(year, month, 1).strftime("%Y-%m-%d")
  156. endTime = datetime.date(year, month, lastDay).strftime("%Y-%m-%d")
  157. return startTime, endTime
  158. def get_start_and_end_by_year(yearStr):
  159. """
  160. 获取年初 和年尾
  161. :param yearStr:
  162. :return:
  163. """
  164. return "{}-01-01".format(yearStr), "{}-12-31".format(yearStr)
  165. def get_date_range(st, et, freq='D', reverse = True):
  166. if reverse:
  167. return list(reversed(date_range(st, et, freq=freq).tolist()))
  168. else:
  169. return list(date_range(st, et, freq=freq).tolist())
  170. def get_test_point(domain, key):
  171. import os
  172. return os.environ.get('test_{}_{}'.format(domain, key), None)
  173. def support_test_point(point):
  174. if not settings.DEBUG:
  175. return False
  176. import os
  177. test_point = os.environ.get(point, None)
  178. if test_point == 'yes':
  179. return True
  180. else:
  181. return False