settings.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. from wsgiref import headers
  2. from dotenv import load_dotenv, find_dotenv
  3. from pathlib import Path # Python 3.6+ only
  4. import configparser, json, pytz
  5. import requests, os
  6. import pillow_avif
  7. from utils.common import message_queue
  8. import hashlib
  9. from pathlib import Path
  10. import os, stat
  11. TIME_ZONE = pytz.timezone("Asia/Shanghai")
  12. from numpy import true_divide
  13. from databases import (
  14. create_all_database,
  15. DeviceConfig,
  16. SysConfigs,
  17. CRUD,
  18. batch_insert_sys_configs,
  19. SqlQuery,
  20. batch_insert_device_configs,
  21. batch_insert_device_configsNew,
  22. )
  23. USER_TOKEN = None # 可以通过外部设置或从配置文件中加载
  24. USER_ENV = None # 可以通过外部设置或从配置文件中加载
  25. USER_CAMERAS = False # 可以通过外部设置或从配置文件中加载
  26. # 追加配置参数 machine_type 拍照机设备类型;0鞋;1服装
  27. MACHINE_TYPE = 0
  28. # 初始化数据表
  29. create_all_database()
  30. session = SqlQuery()
  31. device_config_crud = CRUD(DeviceConfig)
  32. all_devices = device_config_crud.read_all(session)
  33. if len(all_devices) == 0:
  34. # 如果配置表中一条数据都没有,就将初始化数据全部插入到数据表中
  35. action_tabs = json.load(open("action_tabs.json", encoding="utf-8"))
  36. actions = json.load(open("action.json", encoding="utf-8"))
  37. batch_insert_device_configs(session, action_tabs, actions)
  38. sys_config_crud = CRUD(SysConfigs)
  39. all_sys_configs = sys_config_crud.read_all(session)
  40. if len(all_sys_configs) == 0:
  41. # 如果配置表中一条数据都没有,就将初始化数据全部插入到数据表中
  42. sys_config_json = json.load(open("sys_configs.json", encoding="utf-8"))
  43. batch_insert_sys_configs(session, sys_config_json)
  44. else:
  45. # 查询数据库中缺失哪个数据,进行补充
  46. sys_config_json = json.load(open("sys_configs.json", encoding="utf-8"))
  47. for sys_config in sys_config_json:
  48. photos = CRUD(SysConfigs)
  49. item = photos.read(session, conditions={"key": sys_config.get("key")})
  50. if item == None:
  51. config = SysConfigs(**sys_config)
  52. session.add(config)
  53. session.commit() # 合并事务提交
  54. session.close()
  55. # 初始化数据表---结束
  56. def get_config_by_items(config_dict):
  57. __config_dict = {}
  58. for i, k in config_dict:
  59. __config_dict[i] = k
  60. return __config_dict
  61. keys = ["面料", "里料"]
  62. def sync_sys_configs2Online():
  63. hlm_token = USER_TOKEN
  64. headers = {
  65. "Authorization": f"Bearer {hlm_token}",
  66. "content-type": "application/json",
  67. }
  68. # 追加配置参数 machine_type 拍照机设备类型;0鞋;1服装
  69. session = SqlQuery()
  70. sysConfigs = CRUD(SysConfigs)
  71. all_configs = sysConfigs.read_all(session)
  72. localConfigData = {}
  73. for local_config in all_configs:
  74. localConfigData[local_config.key] = json.loads(local_config.value)
  75. data_json = json.dumps(
  76. {"configs": localConfigData, "machine_type": MACHINE_TYPE},
  77. ensure_ascii=False,
  78. )
  79. # 同步本地到线上
  80. url = DOMAIN + "/api/ai_image/camera_machine/update_all_user_configs"
  81. res = requests.post(url=url, headers=headers, data=data_json)
  82. print("res", res.content)
  83. session.close()
  84. def getSysConfigs(key, item, default=None):
  85. session = SqlQuery()
  86. crud = CRUD(SysConfigs)
  87. one_item = crud.read(session, conditions={"key": key})
  88. config = json.loads(one_item.value)
  89. session.close()
  90. if item == "image_out_format":
  91. default_format = config.get(item, default)
  92. if default_format == "" or default_format == None:
  93. return "png"
  94. return config.get(item, default)
  95. def updateSysConfigs(params):
  96. session = SqlQuery()
  97. sysConfig = CRUD(SysConfigs)
  98. # 如果value是字典或列表,需要转换为JSON字符串
  99. if "value" in params and isinstance(params["value"], (dict, list)):
  100. params["value"] = json.dumps(params["value"], ensure_ascii=False)
  101. # 走编辑逻辑
  102. # kws = params.__dict__
  103. sysConfig.updateConditions(session, conditions={"key": params["key"]}, **params)
  104. session.close()
  105. def get_dict_value(_dict, key, default=None):
  106. if key in _dict:
  107. return _dict[key]
  108. else:
  109. return default
  110. # 鞋设备为1 服装设备为5
  111. MCU_CODE = 1
  112. MACHINE_LEVEL = (
  113. "二档"
  114. if not getSysConfigs("other_configs", "device_speed", "二档")
  115. else getSysConfigs("other_configs", "device_speed", "二档")
  116. )
  117. IS_TEST = False
  118. IS_MCU = True
  119. IS_LIN_SHI_TEST = False
  120. PhotographSeconds = float(
  121. 0.5
  122. if not getSysConfigs("take_photo_configs", "camera_delay", "0.5")
  123. else getSysConfigs("take_photo_configs", "camera_delay", "0.5")
  124. ) # 拍照停留时间
  125. MAX_PIXIAN_SIZE = 12000000
  126. def moveSpeed(level: str = None):
  127. config = {
  128. "一档": {
  129. "camera_high_motor": {
  130. "max_speed": 10000,
  131. "up_speed": 800,
  132. "down_speed": 700,
  133. },
  134. "turntable_steering": {
  135. "max_speed": 6000,
  136. "up_speed": 500,
  137. "down_speed": 400,
  138. },
  139. },
  140. "二档": {
  141. "camera_high_motor": {
  142. "max_speed": 7000,
  143. "up_speed": 600,
  144. "down_speed": 500,
  145. },
  146. "turntable_steering": {
  147. "max_speed": 4500,
  148. "up_speed": 350,
  149. "down_speed": 300,
  150. },
  151. },
  152. "三档": {
  153. "camera_high_motor": {
  154. "max_speed": 3500,
  155. "up_speed": 400,
  156. "down_speed": 300,
  157. },
  158. "turntable_steering": {
  159. "max_speed": 3000,
  160. "up_speed": 200,
  161. "down_speed": 200,
  162. },
  163. },
  164. }
  165. if level is None:
  166. return config[MACHINE_LEVEL]
  167. else:
  168. return config[level]
  169. config = configparser.ConfigParser()
  170. config_name = "config.ini"
  171. config.read(config_name, encoding="utf-8")
  172. # 应用名称
  173. APP_NAME = config.get("app", "app_name")
  174. # 应用版本号
  175. APP_VERSION = config.get("app", "version")
  176. # 是否开启调试模式
  177. IS_DEBUG = config.get("app", "debug")
  178. IS_UPLOAD_HLM = True if config.get("app", "is_upload") == "true" else False
  179. # 应用端口号
  180. PORT = config.get("app", "port")
  181. # 应用线程数
  182. APP_WORKS = config.get("app", "works")
  183. # 应用host地址
  184. APP_HOST = config.get("app", "host")
  185. # 应用服务启动名称
  186. APP_RUN = config.get("app", "app_run")
  187. # 日志名称
  188. LOG_FILE_NAME = config.get("log", "log_file_name")
  189. # 最大字节数
  190. MAX_BYTES = config.get("log", "max_bytes")
  191. print("Max bytes is", MAX_BYTES)
  192. # 备份数量
  193. BACKUP_COUNTS = config.get("log", "backup_counts")
  194. # 远程服务器地址
  195. HLM_HOST = config.get("log", "hlm_host")
  196. PROJECT = config.get("app", "project")
  197. # 电子秤配置名称
  198. SCALE_NAME = config.get("electronic_scale", "scale_name")
  199. # ----------------------------------
  200. mcu_config_dict = config.items("mcu_config")
  201. _mcu_config_dict = {}
  202. for i, k in mcu_config_dict:
  203. _mcu_config_dict[i] = int(k)
  204. # print(_mcu_config_dict)
  205. _config_mcu_config = get_config_by_items(config.items("mcu_config"))
  206. LEFT_FOOT_ACTION = _mcu_config_dict["left_foot_action"]
  207. LEFT_FOOT_PHOTOGRAPH = _mcu_config_dict["left_foot_photograph"]
  208. LEFT_FOOT_ACTION_1 = _mcu_config_dict["left_foot_action_1"]
  209. LEFT_FOOT_ACTION_2 = _mcu_config_dict["left_foot_action_2"]
  210. RIGHT_FOOT_ACTION = _mcu_config_dict["right_foot_action"]
  211. RIGHT_FOOT_PHOTOGRAPH = _mcu_config_dict["right_foot_photograph"]
  212. RIGHT_FOOT_ACTION_1 = _mcu_config_dict["right_foot_action_1"]
  213. RIGHT_FOOT_ACTION_2 = _mcu_config_dict["right_foot_action_2"]
  214. NEXT_STEP = int(get_dict_value(_config_mcu_config, "next_step", 6)) # 下一步
  215. MOVE_UP = _mcu_config_dict["move_up"]
  216. MOVE_DOWN = _mcu_config_dict["move_down"]
  217. STOP = _mcu_config_dict["stop"]
  218. # camera_config_dict = config.items("camera_config")
  219. # _camera_config_dict = {}
  220. # for i, k in mcu_config_dict:
  221. # _camera_config_dict[i] = int(k)
  222. # _camera_config_dict = get_config_by_items(camera_config_dict)
  223. # LOW_ISO = _camera_config_dict["low_iso"]
  224. # HIGH_ISO = _camera_config_dict["high_iso"]
  225. DOMAIN = (
  226. "https://dev2.valimart.net"
  227. if config.get("app", "env") != "dev"
  228. else "https://dev2.pubdata.cn"
  229. )
  230. def getDoman(env):
  231. return "https://dev2.valimart.net" if env != "dev" else "https://dev2.pubdata.cn"
  232. Company = "惠利玛"
  233. is_test_plugins = true_divide
  234. OUT_PIC_MODE = "." + getSysConfigs("basic_configs", "image_out_format", "png") # ".png"
  235. OUT_PIC_SIZE = (
  236. [1600]
  237. if getSysConfigs("basic_configs", "main_image_size", [1600]) == ""
  238. else getSysConfigs("basic_configs", "main_image_size", [1600])
  239. ) # 主图大小
  240. Mode = getSysConfigs("other_configs", "product_type", "鞋类") # 程序执行类
  241. OUT_PIC_FACTOR = float(
  242. 1
  243. if getSysConfigs("basic_configs", "image_sharpening", "1") == ""
  244. else getSysConfigs("basic_configs", "image_sharpening", "1")
  245. ) # 图片锐化
  246. RESIZE_IMAGE_MODE = 1
  247. GRENERATE_MAIN_PIC_BRIGHTNESS = 254 # 色阶是否调整到位判断
  248. RUNNING_MODE = getSysConfigs("other_configs", "running_mode", "普通模式")
  249. DEFAULT_CUTOUT_MODE = getSysConfigs("other_configs", "cutout_mode", "普通抠图")
  250. CUTOUT_MODE = (
  251. 0 if getSysConfigs("other_configs", "cutout_mode", "普通抠图") == "普通抠图" else 1
  252. )
  253. import importlib
  254. OUT_PIC_QUALITY = "普通"
  255. GRENERATE_MAIN_PIC_BRIGHTNESS = int(
  256. getSysConfigs("other_configs", "grenerate_main_pic_brightness", 254)
  257. ) # 色阶是否调整到位判断
  258. SHADOW_PROCESSING = int(
  259. getSysConfigs("other_configs", "shadow_processing", 0)
  260. ) # 0表示要直线和曲线,1 表示只要直线
  261. LOWER_Y = int(
  262. getSysConfigs("other_configs", "lower_y", 4)
  263. ) # 鞋底以下多少距离作为阴影蒙版
  264. CHECK_LOWER_Y = int(
  265. getSysConfigs("other_configs", "check_lower_y", 4)
  266. ) # 检测亮度区域,倒数第几行
  267. IS_GET_GREEN_MASK = (
  268. True if getSysConfigs("other_configs", "is_get_green_mask", "否") == "是" else False
  269. ) # 是否进行绿幕抠图
  270. IMAGE_SAVE_MAX_WORKERS = int(
  271. getSysConfigs("other_configs", "image_save_max_workers", 20)
  272. ) # 批量保存的线程大小
  273. COLOR_GRADATION_CYCLES = int(
  274. getSysConfigs("other_configs", "color_gradation_cycles", 23)
  275. ) # 色阶处理循环次数
  276. # grenerate_main_pic_brightness 亮度范围 默认值254 范围 200 -255 步长 1
  277. # opacity 透明度 默认值 0.5 范围 0.5-1 步长 0.1
  278. # IMAGE_MASK_CONFIG = int(
  279. # getSysConfigs("basic_configs", "image_mask_config", {"mode":0,"opacity":0.5,"grenerate_main_pic_brightness":254})
  280. # ) # 色阶处理循环次数
  281. def recordDataPoint(token=None, page="", uuid=None, data=""):
  282. """记录日志"""
  283. if token == None:
  284. return
  285. if page == "":
  286. return
  287. if uuid == None:
  288. return
  289. headers = {"Content-Type": "application/json", "authorization": "Bearer " + token}
  290. params = {
  291. "site": 1,
  292. "type": 5,
  293. "channel": "aigc-camera",
  294. "uuid": uuid,
  295. "page": page,
  296. "page_url": "/",
  297. "describe": {"action": page, "data": data},
  298. "time": 0,
  299. }
  300. return requests.post(
  301. headers=headers, data=json.dumps(params), url=DOMAIN + "/api/record/point"
  302. )
  303. def syncPhotoRecord(data, action_type=0):
  304. """同步图片记录"""
  305. headers = {
  306. "Authorization": f"Bearer {USER_TOKEN}",
  307. "content-type": "application/json",
  308. }
  309. machine_type = MACHINE_TYPE
  310. url = getDoman(USER_ENV) + f"/api/ai_image/camera_machine/photo_records_handler"
  311. postData = {"data": data, "machine_type": machine_type, 'action_type': action_type}
  312. response = requests.post(url=url, data=json.dumps(postData, ensure_ascii=False, default=str), headers=headers)
  313. print("用户token", response.content)
  314. def syncBatchPhotoRecordDelete():
  315. """同步图片记录"""
  316. headers = {
  317. "Authorization": f"Bearer {USER_TOKEN}",
  318. "content-type": "application/json",
  319. }
  320. machine_type = MACHINE_TYPE
  321. url = getDoman(USER_ENV) + f"/api/ai_image/camera_machine/photo_records_handler"
  322. postData = {"machine_type": machine_type, "action_type": 4}
  323. response = requests.post(
  324. url=url,
  325. data=json.dumps(postData, ensure_ascii=False, default=str),
  326. headers=headers,
  327. )
  328. print("用户token", response.content)
  329. def checkRecordSyncStatus():
  330. # check_photo_record_sync_status
  331. headers = {
  332. "Authorization": f"Bearer {USER_TOKEN}",
  333. "content-type": "application/json",
  334. }
  335. machine_type = MACHINE_TYPE
  336. url = getDoman(USER_ENV) + f"/api/ai_image/camera_machine/photo_records_handler?machine_type={machine_type}"
  337. try:
  338. response = requests.get(url=url, headers=headers).json()
  339. return response.get("data").get('status', True)
  340. except Exception as e:
  341. return True
  342. async def sendSocketMessage(
  343. code=0, msg="", data=None, device_status=2, msg_type=""
  344. ):
  345. data = {
  346. "code": code,
  347. "msg": msg,
  348. "status": device_status,
  349. "data": data,
  350. "msg_type": msg_type,
  351. }
  352. await message_queue.put(data)
  353. def calculate_md5(filepath):
  354. # 打开文件,以二进制只读模式打开
  355. with open(filepath, "rb") as f:
  356. # 创建MD5哈希对象
  357. md5hash = hashlib.md5()
  358. # 循环读取文件的内容并更新哈希对象
  359. for chunk in iter(lambda: f.read(4096), b""):
  360. md5hash.update(chunk)
  361. # 返回MD5哈希的十六进制表示
  362. return md5hash.hexdigest()
  363. __output_dir = config.get("output_config", "output_dir")
  364. path_obj = Path(os.path.abspath(__output_dir))
  365. OUTPUT_DIR = path_obj.absolute()
  366. print("OUTPUT_DIR", __output_dir, OUTPUT_DIR)
  367. def handle_remove_readonly(func, path, exc):
  368. os.chmod(path, stat.S_IWRITE)
  369. func(path)
  370. try:
  371. __scan_dir = config.get("scan_config", "scan_dir")
  372. if __scan_dir == "" or __scan_dir is None:
  373. SCAN_DIR = None
  374. else:
  375. scan_path_obj = Path(os.path.abspath(__scan_dir))
  376. SCAN_DIR = scan_path_obj.absolute()
  377. if not os.path.exists(SCAN_DIR):
  378. # 创建多级目录
  379. os.makedirs(SCAN_DIR, exist_ok=True)
  380. except:
  381. SCAN_DIR = None
  382. print('扫码配置不存在')
  383. print("SCAN_DIR", SCAN_DIR)
  384. CUSTOMER_TEMPLATE_URL = config.get("customer_template", "template_url")
  385. def hex_to_rgb(hex_color):
  386. """
  387. 将十六进制颜色值转换为RGB颜色值
  388. :param hex_color: 十六进制颜色值,例如 "#FF0000" 或 "FF0000"
  389. :return: RGB元组,例如 (255, 0, 0)
  390. """
  391. # 移除可能存在的 # 符号
  392. hex_color = hex_color.lstrip('#')
  393. # 确保是有效的十六进制字符串
  394. if len(hex_color) != 6:
  395. raise ValueError("十六进制颜色值格式不正确,应为6位十六进制数")
  396. # 将十六进制字符串转换为RGB值
  397. try:
  398. r = int(hex_color[0:2], 16)
  399. g = int(hex_color[2:4], 16)
  400. b = int(hex_color[4:6], 16)
  401. return (r, g, b)
  402. except ValueError:
  403. return (255, 255, 255)
  404. def rgb_to_hex(r, g, b):
  405. """
  406. 将RGB颜色值转换为十六进制颜色值
  407. :param r: 红色分量 (0-255)
  408. :param g: 绿色分量 (0-255)
  409. :param b: 蓝色分量 (0-255)
  410. :return: 十六进制颜色值,例如 "#FF0000"
  411. """
  412. # 验证RGB值在有效范围内
  413. if not all(0 <= val <= 255 for val in [r, g, b]):
  414. return "#FFFFFF"
  415. return "#{:02X}{:02X}{:02X}".format(r, g, b)