Commit aa06284d 刘韬

稳定版

1 个父辈 4d9f2edd
正在显示 134 个修改的文件 包含 295 行增加2039 行删除
smartshelf/app/__pycache__
<?xml version="1.0" encoding="UTF-8"?>
<config ver="10">
<item key="ipstart" ver="10" value="192.168.101.50" />
<item key="ipend" ver="10" value="60" />
</config>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<config ver="10">
<item key="ipstart" ver="10" value="192.168.101.50" />
<item key="ipend" ver="10" value="2" />
</config>
\ No newline at end of file \ No newline at end of file
{"192.168.101.56":{"IP":"192.168.101.56","Mac":"","Host":null,"BoardType":3,"Ver":0.0,"MCAddr":null,"PingDelay":21,"shelfState":{"isupdate":false,"state":"na","msg":null,"ipconfig":null,"version":null,"serial_state":"na","ad_serial":null},"memo":null},"192.168.101.53":{"IP":"192.168.101.53","Mac":"","Host":null,"BoardType":0,"Ver":0.0,"MCAddr":null,"PingDelay":15,"shelfState":{"isupdate":true,"state":"on","msg":"未进行测试动作","ipconfig":{"post":"wait","ip":"http://192.168.101.77/smf-core","cid":"002"},"version":"1.3","serial_state":null,"ad_serial":null},"memo":null},"192.168.101.52":{"IP":"192.168.101.52","Mac":"","Host":null,"BoardType":0,"Ver":0.0,"MCAddr":null,"PingDelay":62,"shelfState":{"isupdate":true,"state":"on","msg":"未进行测试动作","ipconfig":{"post":"wait","ip":"http://192.168.101.77/smf-core","cid":"003"},"version":"1.3","serial_state":null,"ad_serial":null},"memo":null},"192.168.101.51":{"IP":"192.168.101.51","Mac":"","Host":null,"BoardType":0,"Ver":0.0,"MCAddr":null,"PingDelay":12,"shelfState":{"isupdate":true,"state":"on","msg":"未进行测试动作","ipconfig":{"post":"wait","ip":"http://192.168.101.77/smf-core","cid":"001"},"version":"1.3","serial_state":null,"ad_serial":null},"memo":null},"192.168.101.50":{"IP":"192.168.101.50","Mac":"","Host":null,"BoardType":3,"Ver":0.0,"MCAddr":null,"PingDelay":218,"shelfState":{"isupdate":false,"state":"na","msg":null,"ipconfig":null,"version":null,"serial_state":"na","ad_serial":null},"memo":null}}
\ No newline at end of file \ No newline at end of file
<?xml version="1.0"?>
<doc>
<assembly>
<name>ConfigHelper</name>
</assembly>
<members>
<member name="F:ConfigHelper.AdvanceConfigEdit.CustomEditor">
<summary>
自定义编辑器
</summary>
</member>
<member name="F:ConfigHelper.AdvanceConfigEdit.components">
<summary>
必需的设计器变量。
</summary>
</member>
<member name="M:ConfigHelper.AdvanceConfigEdit.Dispose(System.Boolean)">
<summary>
清理所有正在使用的资源。
</summary>
<param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
</member>
<member name="M:ConfigHelper.AdvanceConfigEdit.InitializeComponent">
<summary>
设计器支持所需的方法 - 不要修改
使用代码编辑器修改此方法的内容。
</summary>
</member>
<member name="M:ConfigHelper.AdvanceConfigForm.AddCustomEditor``1(System.String)">
<summary>
添加自定义编辑器
</summary>
<typeparam name="T"></typeparam>
<param name="name"></param>
</member>
<member name="M:ConfigHelper.AdvanceConfigForm.ShowEditDialog(System.Windows.Forms.IWin32Window,System.Boolean)">
<summary>
显示配置界面,2秒内调用约6次后显示
</summary>
<param name="owner"></param>
<param name="TopMost"></param>
</member>
<member name="F:ConfigHelper.AdvanceConfigForm.components">
<summary>
Required designer variable.
</summary>
</member>
<member name="M:ConfigHelper.AdvanceConfigForm.Dispose(System.Boolean)">
<summary>
Clean up any resources being used.
</summary>
<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
</member>
<member name="M:ConfigHelper.AdvanceConfigForm.InitializeComponent">
<summary>
Required method for Designer support - do not modify
the contents of this method with the code editor.
</summary>
</member>
<member name="T:ConfigHelper.Config">
<summary>
自定义配置存取
</summary>
</member>
<member name="F:ConfigHelper.Config.hasChange">
<summary>
指示配置文件是否存在变化
</summary>
</member>
<member name="P:ConfigHelper.Config.SaveToAppdata">
<summary>
将设置保存至appdata目录
</summary>
</member>
<member name="M:ConfigHelper.Config.ReloadConfig">
<summary>
重载配置
</summary>
</member>
<member name="M:ConfigHelper.Config.SetComment(System.String,System.String)">
<summary>
设置备注
</summary>
<param name="key"></param>
<param name="Comment"></param>
</member>
<member name="M:ConfigHelper.Config.Get(System.String)">
<summary>
读取配置
</summary>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:ConfigHelper.Config.Get(System.Object)">
<summary>
读取配置
</summary>
<param name="key">传入一个枚举值</param>
<returns></returns>
</member>
<member name="M:ConfigHelper.Config.Get``1(System.Object,``0)">
<summary>
读取配置
</summary>
<typeparam name="T">返回类型</typeparam>
<param name="key">传入一个枚举值</param>
<param name="defaultvalue">失败默认值</param>
<returns></returns>
</member>
<member name="M:ConfigHelper.Config.Get``1(System.String,``0)">
<summary>
读取配置
</summary>
<typeparam name="T">返回类型</typeparam>
<param name="key">key</param>
<param name="defaultvalue">失败默认值</param>
<returns></returns>
</member>
<member name="M:ConfigHelper.Config.Set(System.String,System.String)">
<summary>
设置配置
</summary>
<param name="key"></param>
<param name="value"></param>
</member>
<member name="M:ConfigHelper.Config.Set(System.Object,System.String)">
<summary>
设置配置
</summary>
<param name="key">配置枚举值</param>
<param name="value"></param>
</member>
<member name="M:ConfigHelper.Config.Set``1(System.Object,``0)">
<summary>
设置配置
</summary>
<param name="key">配置枚举值</param>
<param name="value"></param>
</member>
<member name="M:ConfigHelper.Config.Set``1(System.String,``0)">
<summary>
设置配置
</summary>
<typeparam name="T">值类型</typeparam>
<param name="key"></param>
<param name="value"></param>
</member>
<member name="M:ConfigHelper.Config.SaveChangeDebounce">
<summary>
保存设置
</summary>
</member>
<member name="M:ConfigHelper.Config.SaveChange">
<summary>
保存设置
</summary>
</member>
<member name="M:ConfigHelper.Config.PropertyBind(System.Object,System.Object,System.String,System.String,System.String)">
<summary>
绑定UI属性
</summary>
<param name="key">配置key</param>
<param name="uiobj">ui对象</param>
<param name="Property">绑定属性</param>
<param name="SaveEvent">绑定事件(object s, EventArgs x),可以为空</param>
<param name="defaultvalue">默认值</param>
</member>
<member name="M:ConfigHelper.Config.PropertyBind``1(System.Object,System.Object,System.String,System.String,``0)">
<summary>
绑定UI属性
</summary>
<param name="key">配置key</param>
<param name="uiobj">ui对象</param>
<param name="Property">绑定属性</param>
<param name="SaveEvent">绑定事件(object s, EventArgs x),可以为空</param>
<param name="defaultvalue">默认值</param>
</member>
<member name="M:ConfigHelper.Config.LoadMyConfig(System.Type)">
<summary>
转换自定义配置类
</summary>
<param name="ConfigClassType"></param>
<returns>加载到的配置Key数量</returns>
</member>
<member name="T:ConfigHelper.ICustEditor">
<summary>
自定义编辑器接口
</summary>
</member>
<member name="M:ConfigHelper.ICustEditor.ValueEdit(System.Object)">
<summary>
自己的编辑方法或界面
</summary>
<param name="value">传入的值</param>
<returns>传出的值</returns>
</member>
<member name="T:ConfigHelper.MyConfig`1">
<summary>
自动化我的配置
</summary>
</member>
<member name="F:ConfigHelper.MyConfig`1.Key">
<summary>
配置的Key
</summary>
</member>
<member name="P:ConfigHelper.MyConfig`1.Val">
<summary>
配置的值
</summary>
</member>
<member name="M:ConfigHelper.MyConfig`1.ToString">
<summary>
获取配置数据的文本
</summary>
<returns></returns>
</member>
<member name="M:ConfigHelper.MyConfig`1.op_Implicit(ConfigHelper.MyConfig{`0})~`0">
<summary>
隐式转换
</summary>
<param name="m1"></param>
</member>
<member name="M:ConfigHelper.MyConfig`1.op_Implicit(`0)~ConfigHelper.MyConfig{`0}">
<summary>
隐式转换
</summary>
<param name="v1"></param>
</member>
<member name="T:ConfigHelper.MyConfigComment">
<summary>
自定义配置描述
</summary>
</member>
<member name="M:ConfigHelper.MyConfigComment.#ctor(System.String)">
<summary>
配置的说明
</summary>
<param name="comment"></param>
</member>
</members>
</doc>
# codinf:utf-8
import os
import time
from flask import render_template, Response, request,redirect,url_for
from werkzeug.utils import secure_filename
from app import app
import logging
import pexpect
import json
import zipfile
import shutil
import csv
import requests
import re
from config import Config
basepath = os.path.dirname(__file__)
def backup():
try:
source_dir = '/prog/backup/'
today = source_dir + time.strftime('%Y%m%d')
if not os.path.exists(today):
os.mkdir(today)
cmd = "cp -rf /prog/smartshelf/* /prog/backup/{}/".format(time.strftime('%Y%m%d'))
run = pexpect.spawn('su -c "%s" root' %cmd)
time.sleep(2)
run.sendline('xxx')
logging.warning("备份成功")
except Exception as e:
logging.warning("备份失败:{}".format(e))
def read_ip():
uploads_path = basepath + Config.STATE_PATH
with open(uploads_path + 'ipconfig.csv','r') as f:
reader = csv.reader(f)
current = [row for row in reader]
ip = current[0][0]
return ip
def read_version():
uploads_path = basepath + Config.STATE_PATH
with open(uploads_path + "version.txt","r") as f:
s_version=f.readline()
return s_version
def confirm_version(version):
logging.warning("写入最新版本号:{}".format(version))
uploads_path = basepath + Config.STATE_PATH
with open(uploads_path + "version.txt","w") as f:
f.write(str(version))
f.close()
@app.route('/upgrade',methods=['POST'])
def upgrade():
ip = read_ip()
ip = ip.replace('/smdbox', '')
# ip = 'http://192.168.1.99'
download_url = '{}/download/version.txt'.format(ip)
logging.warning("服务器最新版本信息:{}".format(download_url))
try:
response = requests.get(download_url)
if response.status_code == 200:
version = response.json()
s_version = read_version()
logging.warning("当前版本:{},最新版本:{}".format(s_version,version))
if str(s_version) == str(version):
info = {'operation':'当前版本已是最新版本!'}
else:
download_zip(ip,version)
backup()
time.sleep(2)
process_file()
time.sleep(2)
confirm_version(version)
reboot()
info = {'operation':'已升级到最新版本'}
else:
info = {'operation':'服务器地址错误'}
except Exception as e:
logging.warning("发生错误:{}".format(e))
info = {'operation':'发生错误'}
return json.dumps(info)
def download_zip(ip,version):
zip_url = '{}/download/{}.zip'.format(ip,version)
logging.warning("服务器最新文件:{}".format(zip_url))
target_path = '/prog/upgrade_cach/smartshelf.zip'
File=requests.get(zip_url, stream=True)
with open(target_path,'wb+') as f:
for chunk in File.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
f.close()
def process_file():
zfile = zipfile.ZipFile('/prog/upgrade_cach/smartshelf.zip','r')
path2 = '/prog/update/smartshelf/'
n_train = 0
for filename in zfile.namelist():
if filename.endswith('/'):
n_train += 1
os.makedirs(os.path.join(path2, filename))
else:
data = zfile.read(filename)
file = open(os.path.join(path2, filename), 'w+b')
file.write(data)
file.close()
time.sleep(5)
py_source = '/prog/update/smartshelf/app/'
templates_source = '/prog/update/smartshelf/app/templates/'
py_target = '/prog/smartshelf/app/'
template_target = '/prog/smartshelf/app/templates/'
templates_lis = os.listdir(path=templates_source)
py_lis = os.listdir(path=py_source)
logging.warning("待更新文件:{},{}".format(py_lis,templates_lis))
for t_file in templates_lis:
t_filename = os.path.join(templates_source,t_file)
if os.path.isfile(t_filename):
try:
shutil.copy(t_filename, template_target)
except IOError as e:
logging.warning("Unable to copy file. %s" % e)
# print("Unable to copy file. %s" % e)
except Exception as e:
logging.warning("Unexpected error: %s" % e)
for p_file in py_lis:
p_filename = os.path.join(py_source,p_file)
if os.path.isfile(p_filename):
try:
shutil.copy(p_filename, py_target)
except IOError as e:
logging.warning("Unable to copy file. %s" % e)
except Exception as e:
logging.warning("Unexpected error: %s" % e)
shutil.rmtree(path2)
os.remove('/prog/upgrade_cach/smartshelf.zip')
# shutil.rmtree('/prog/upgrade_cach/')
logging.warning("templates upgrade success")
def reboot():
os.system('/prog/./restart.sh')
def openteam():
# os.system('/usr/bin/./teamviwer')
cmd = "nohub /opt/teamviewer/tv_bin/TeamViewer"
run = pexpect.spawn('su -c "%s" root' %cmd)
time.sleep(0.5)
run.sendline('xxx')
# cmd1 = "./teamviwer"
# run1 = pexpect.spawn('su -c "%s" root' %cmd1)
# time.sleep(0.5)
# run1.sendline('xxx')
logging.warning("teamview open")
@app.route('/openteamview',methods=['POST'])
def openteamview():
openteam()
info = {'operation':'已打开teamview'}
return json.dumps(info)
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
config and init 24-LEDs-stripe
"""
import os
from matplotlib.pyplot import cla
LED_COUNT = 1000 # 要控制LED的数量.
# LED_PIN = 18 # GPIO接口 (PWM编码).
LED_BRIGHTNESS = 100 # 设置LED亮度 (0-255)
#以下LED配置无需修改
LED_FREQ_HZ = 800000 # LED信号频率(以赫兹为单位)(通常为800khz)
LED_DMA = 10 # 用于生成信号的DMA通道(尝试5)
LED_INVERT = False # 反转信号(使用NPN晶体管电平移位时)
LED_CHANNEL = 0
stop_flag = None
stripStore={}
if os.name != 'nt':
from neopixel import *
from rpi_ws281x import Adafruit_NeoPixel, Color as ColorA,PixelStrip
#Color=ColorA
def Color(red,green, blue, white=0):
return ColorA(green,red,blue)
def get_strip(pin=12):
LED_PIN = pin
if stripStore.get(LED_PIN) is None:
stripStore[LED_PIN] = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS,LED_CHANNEL)
stripStore[LED_PIN].begin()
# Initialize the library (must be called once before other functions).
# log.debug("Initialize: " + str(strip))
return stripStore[LED_PIN]
def color_wipe_full(strip, color, wait_ms=50):
"""Wipe color across display a pixel at a time."""
for i in range(strip.numPixels()):
strip.setPixelColor(i, color)
strip.show()
# time.sleep(wait_ms/1000.0)
def reset_strip(strip):
strip.setBrightness(LED_BRIGHTNESS)
color_wipe_full(strip, Color(0,0,0), 20)
# log.debug('LED stripe cleared.')
return
# noinspection PyProtectedMember
def _cleanup_strip(strip: Adafruit_NeoPixel):
strip._cleanup()
else:
class strip:
def numPixels():
return 1
def setPixelColor(i,c):
return
def show():
return
def Color(red,green, blue, white=0):
return (white << 24) | (red << 16) | (green << 8) | blue
def get_strip(pin=12):
if stripStore.get(pin) is None:
stripStore[pin] = strip
print('new_strip:'+str(pin))
print('get_strip:'+str(pin))
return stripStore[pin]
def color_wipe_full(strip, color, wait_ms=50):
print(color)
# time.sleep(wait_ms/1000.0)
def reset_strip(strip):
print('reset_strip:\/')
print(strip)
# log.debug('LED stripe cleared.')
return
# noinspection PyProtectedMember
def _cleanup_strip(strip):
print(strip)
def setcolor(color):
color = color.lower()
if color == 'red':
return Color(255,0,0)
elif color == 'green':
return Color(0,255,0)
elif color == 'yellow':
return Color(255,255,0)
elif color == 'off':
return Color(0,0,0)
elif color == 'blue':
return Color(0,0,255)
elif color == 'orange':
return Color(255,97,0)
elif color == 'cyan':
return Color(0,255,255)
elif color == 'firebrick':
return Color(178,34,34)
elif color == 'purple':
return Color(128,0,128)
elif color == 'forestgreen':
return Color(34,139,34)
elif color == 'lightblue':
return Color(173,216,230)
elif color == 'indianred':
return Color(205,92,92)
elif color == 'darkgreen':
return Color(0,100,0)
elif color == 'white':
return Color(255,255,255)
elif color == 'magenta':
return Color(255,0,255)
else:
return Color(255,255,255)
\ No newline at end of file \ No newline at end of file
1.4
\ No newline at end of file \ No newline at end of file
import pickle
import os
from enum import Enum, auto
import string
import logging
from config import Config
basepath = os.path.dirname(__file__)
shelfconfigfile = basepath + Config.STATE_PATH+'shelfconfig.pkl'
class LEDColorSort(Enum):
GRB = 1
RGB = 2
class _shelfconfig:
def __init__(self):
self.LED_ColorSort = LEDColorSort.RGB.value
self.LED_COUNT=1000
self.TOWER_CUSTCONTROL=0
def Save(self):
with open(shelfconfigfile, 'wb') as f:
pickle.dump(self, f)
shelfconfig:_shelfconfig
shelfconfig = _shelfconfig()
if os.path.exists(shelfconfigfile):
with open(shelfconfigfile, 'rb') as f:
a = pickle.load(f)
for it in a.__dict__.items():
if it[0].find('__')>=0 or it[0]=='Save':
continue
if shelfconfig.__dict__.get(it[0]) is not None:
shelfconfig.__dict__[it[0]]=a.__dict__[it[0]]
...@@ -5,10 +5,13 @@ config and init 24-LEDs-stripe ...@@ -5,10 +5,13 @@ config and init 24-LEDs-stripe
""" """
import os import os
import logging
from app.g import shelfconfig, LEDColorSort
from matplotlib.pyplot import cla from matplotlib.pyplot import cla
LED_COUNT = 1000 # 要控制LED的数量. LED_COUNT = 1000 # 要控制LED的数量.
#2400
#GRB
# LED_PIN = 18 # GPIO接口 (PWM编码). # LED_PIN = 18 # GPIO接口 (PWM编码).
LED_BRIGHTNESS = 100 # 设置LED亮度 (0-255) LED_BRIGHTNESS = 100 # 设置LED亮度 (0-255)
#以下LED配置无需修改 #以下LED配置无需修改
...@@ -26,11 +29,19 @@ if os.name != 'nt': ...@@ -26,11 +29,19 @@ if os.name != 'nt':
#Color=ColorA #Color=ColorA
def Color(red,green, blue, white=0): def Color(red,green, blue, white=0):
return ColorA(green,red,blue) if shelfconfig.LED_ColorSort == LEDColorSort.RGB.value:
return ColorA(red,green,blue)
else:
return ColorA(green,red,blue)
def get_strip(pin=12): def get_strip(pin=12):
LED_PIN = pin LED_PIN = pin
if stripStore.get(LED_PIN) is None: if stripStore.get(LED_PIN) is None:
LED_COUNT = shelfconfig.LED_COUNT
print('LED_COUNT:',str(LED_COUNT))
print('LED_ColorSort:',str(shelfconfig.LED_ColorSort))
logging.info('LED_COUNT:'+str(LED_COUNT))
logging.info('LED_ColorSort:'+str(shelfconfig.LED_ColorSort))
stripStore[LED_PIN] = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS,LED_CHANNEL) stripStore[LED_PIN] = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS,LED_CHANNEL)
stripStore[LED_PIN].begin() stripStore[LED_PIN].begin()
# Initialize the library (must be called once before other functions). # Initialize the library (must be called once before other functions).
......
...@@ -15,7 +15,7 @@ from time import sleep ...@@ -15,7 +15,7 @@ from time import sleep
from config import Config from config import Config
#from rpi_ws281x import Adafruit_NeoPixel, Color,PixelStrip #from rpi_ws281x import Adafruit_NeoPixel, Color,PixelStrip
from app import app,babel from app import app,babel
# from app import socketio from app.g import shelfconfig as shelfconfigA
from app.led_strip import get_strip,Color,setcolor from app.led_strip import get_strip,Color,setcolor
from app import driver_gpio from app import driver_gpio
import logging import logging
...@@ -61,14 +61,6 @@ SET_LED_CHANNEL = {'1':12,'2':21} ...@@ -61,14 +61,6 @@ SET_LED_CHANNEL = {'1':12,'2':21}
led_lights1 = {} led_lights1 = {}
led_lights2 = {} led_lights2 = {}
# @app.route('/taillog',methods=['POST'])
# def taillog():
# a=os.popen("tail -n 20 /prog/smartshelf/logs/smart.log").readlines()
# s = '<br>'
# p = s.join(a)
# jsondata = {'msg':p}
# return json.dumps(jsondata)
#
@app.route('/language/<language>') @app.route('/language/<language>')
def set_language(language=None): def set_language(language=None):
global curren_l global curren_l
...@@ -137,7 +129,7 @@ def SwitchStatusLight(channel,color,onoff): ...@@ -137,7 +129,7 @@ def SwitchStatusLight(channel,color,onoff):
driver_gpio.gpio_high(pin) driver_gpio.gpio_high(pin)
else: else:
driver_gpio.gpio_low(pin) driver_gpio.gpio_low(pin)
msg = _("通道")+":"+str(channel)+";"+_("状态灯")+":{}; onoff:{}".format(channel,color,onoff) msg = _("通道")+":"+str(channel)+";"+_("状态灯")+":{};Pin:{};onoff:{}".format(color,pin,onoff)
logging.warning(msg) logging.warning(msg)
return msg return msg
...@@ -152,7 +144,7 @@ def process_lightindex(data): ...@@ -152,7 +144,7 @@ def process_lightindex(data):
color = set_indexcolor(light_led_color) color = set_indexcolor(light_led_color)
light_led = data['light_led'] light_led = data['light_led']
channel = config_dict.get(light_led).split('@')[1] channel = config_dict.get(light_led).split('@')[1]
led_index = config_dict.get(light_led).split('@')[0] led_index = int(config_dict.get(light_led).split('@')[0])
if channel == '1': if channel == '1':
# global led_lights1 # global led_lights1
if led_index not in led_lights1.keys(): if led_index not in led_lights1.keys():
...@@ -176,7 +168,7 @@ def process_offindex(data): ...@@ -176,7 +168,7 @@ def process_offindex(data):
global led_lights2 global led_lights2
off_led = data['off_led'] off_led = data['off_led']
channel = config_dict.get(off_led).split('@')[1] channel = config_dict.get(off_led).split('@')[1]
led_index = config_dict.get(off_led).split('@')[0] led_index = int(config_dict.get(off_led).split('@')[0])
if channel == '1': if channel == '1':
# global led_lights1 # global led_lights1
if led_index in led_lights1.keys(): if led_index in led_lights1.keys():
...@@ -203,9 +195,11 @@ def ledopen(): ...@@ -203,9 +195,11 @@ def ledopen():
pin = SET_LED_CHANNEL['1'] pin = SET_LED_CHANNEL['1']
strip = get_strip(pin) strip = get_strip(pin)
for key,value in led_lights1.items(): for key,value in led_lights1.items():
c_index=list(map(int,re.split(';',key))) print(key,value)
for on_led in c_index: #c_index=list(map(int,re.split(';',key)))
strip.setPixelColor(on_led, value) on_led=key
#for on_led in c_index:
strip.setPixelColor(on_led, value)
# print ("111") # print ("111")
strip.show() strip.show()
elif channel == '2': elif channel == '2':
...@@ -213,9 +207,10 @@ def ledopen(): ...@@ -213,9 +207,10 @@ def ledopen():
pin = SET_LED_CHANNEL['2'] pin = SET_LED_CHANNEL['2']
strip = get_strip(pin) strip = get_strip(pin)
for key,value in led_lights2.items(): for key,value in led_lights2.items():
c_index=list(map(int,re.split(';',key))) #c_index=list(map(int,re.split(';',key)))
for on_led in c_index: on_led=key
strip.setPixelColor(on_led, value) #for on_led in c_index:
strip.setPixelColor(on_led, value)
strip.show() strip.show()
else: else:
pin1 = SET_LED_CHANNEL['1'] pin1 = SET_LED_CHANNEL['1']
...@@ -436,7 +431,7 @@ def lineledoff(): ...@@ -436,7 +431,7 @@ def lineledoff():
def opAll(): def opAll():
data = request.get_json() data = request.get_json()
info = {"status":0} info = {"status":0}
if data["op"].lower() =="on": ata["op"].lower() =="on":
logging.info('打开所有灯') logging.info('打开所有灯')
return json.dumps(info) return json.dumps(info)
else: else:
...@@ -628,4 +623,96 @@ def rest_api_v1_shelf_allPosOff(): ...@@ -628,4 +623,96 @@ def rest_api_v1_shelf_allPosOff():
strip.setPixelColor(i, Color(0,0,0)) strip.setPixelColor(i, Color(0,0,0))
strip.show() strip.show()
logging.info('完成关闭所有灯') logging.info('完成关闭所有灯')
return 'allPosOff OK'
\ No newline at end of file \ No newline at end of file
return 'allPosOff OK'
@app.route('/rest/api/v1/shelf/keepAlive')
def rest_api_v1_shelf_keepAlive():
return 'OK'
@app.route('/setconfig',methods=['POST'])
def setconfig():
data = request.get_json()
cf={}
for k,v in shelfconfigA.__dict__.items():
if k in data:
print(k,v,data.get(k))
setattr(shelfconfigA,k,data.get(k))
cf[k]=data.get(k)
if len(cf)>0:
shelfconfigA.Save()
return json.dumps(cf)
@app.route('/rest/api/v1/shelf/lightHouse', methods=['GET'])
def rest_api_v1_shelf_lightHouse():
"""
3.6.灯塔控制接口
输入格式: 三色灯@操作;三色灯@操作
三色灯取值: RA,YA,GA,RB,YB,GB
操作: ON/OFF
返回: OK/FAIL
"""
# 灯标识到SET_CHANNEL键的映射
LIGHT_MAP = {
'RA': 'redA',
'YA': 'yellowA',
'GA': 'greenA',
'RB': 'redB',
'YB': 'yellowB',
'GB': 'greenB'
}
try:
# 获取操作参数
operations = request.args.get('op')
if not operations:
return 'FAIL: Missing operations parameter'
# 分割成单独的操作
ops = operations.split(';')
success = True
for op in ops:
if not op:
continue
try:
# 分割每个操作为灯标识和动作
light, action = op.split('@')
light = light.upper()
action = action.upper()
# 获取对应的GPIO引脚
channel_key = LIGHT_MAP.get(light)
if not channel_key:
success = False
logging.warning(f'Invalid light identifier: {light}')
continue
pin = SET_CHANNEL[channel_key]
driver_gpio.init(SET_CHANNEL[channel_key])
# 执行操作
if action == 'ON':
driver_gpio.gpio_high(pin)
logging.info(f'Turned ON {light} (pin: {pin})')
elif action == 'OFF':
driver_gpio.gpio_low(pin)
logging.info(f'Turned OFF {light} (pin: {pin})')
else:
success = False
logging.warning(f'Invalid action: {action}')
except ValueError:
success = False
logging.warning(f'Invalid operation format: {op}')
except KeyError:
success = False
logging.warning(f'Invalid light identifier: {light}')
except Exception as e:
success = False
logging.error(f'Error processing operation {op}: {str(e)}')
return 'OK' if success else 'FAIL'
except Exception as e:
logging.error(f'Error in lightHouse interface: {str(e)}')
return 'FAIL'
\ No newline at end of file \ No newline at end of file
此文件类型无法预览
off
\ No newline at end of file \ No newline at end of file
on
\ No newline at end of file \ No newline at end of file
...@@ -130,7 +130,7 @@ ...@@ -130,7 +130,7 @@
</div> </div>
</div> </div>
<div class="panel panel-success"> <!--div class="panel panel-success">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{{ _('下载库位二维码') }}</h3> <h3 class="panel-title">{{ _('下载库位二维码') }}</h3>
</div> </div>
...@@ -149,7 +149,7 @@ ...@@ -149,7 +149,7 @@
<label for="cha11" class="col-sm-4">{{ _('单个二维码尺寸(含白色底框)尺寸为16*16mm,黑码尺寸为10*10mm') }}</label> <label for="cha11" class="col-sm-4">{{ _('单个二维码尺寸(含白色底框)尺寸为16*16mm,黑码尺寸为10*10mm') }}</label>
</form> </form>
</div> </div>
</div> </div-->
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<h2>{{ _('运行日志&状态信息') }}</h2> <h2>{{ _('运行日志&状态信息') }}</h2>
......
...@@ -111,16 +111,16 @@ ...@@ -111,16 +111,16 @@
<input type="button" value={{ _('保存') }} class="btn btn-info" onclick="updateip()"/> <input type="button" value={{ _('保存') }} class="btn btn-info" onclick="updateip()"/>
</div> </div>
</div> </div>
<div class="panel panel-success"> <!--div class="panel panel-success">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{{ _('控制器备份&升级') }}</h3> <h3 class="panel-title">{{ _('控制器备份&升级') }}</h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<!-- <input type="button" value="软件备份" class="btn btn-info" onclick="backup()"/> --> < !-- <input type="button" value="软件备份" class="btn btn-info" onclick="backup()"/> -- >
<input type="button" value={{ _('料架升级') }} class="btn btn-info" onclick="upgrade()"/> <input type="button" value={{ _('料架升级') }} class="btn btn-info" onclick="upgrade()"/>
<!-- <input type="button" value={{ _('teamview') }} class="btn btn-info" onclick="openteamview()"/> --> < !-- <input type="button" value={{ _('teamview') }} class="btn btn-info" onclick="openteamview()"/> -- >
</div> </div>
</div> </div-->
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<h2>{{ _('运行日志&状态信息') }}</h2> <h2>{{ _('运行日志&状态信息') }}</h2>
......
1.52
\ No newline at end of file \ No newline at end of file
1.684
\ No newline at end of file \ No newline at end of file
...@@ -18,4 +18,5 @@ class Config(object): ...@@ -18,4 +18,5 @@ class Config(object):
ALLOWED_EXTENSIONS = set(['csv']) #限制上传文件格式 ALLOWED_EXTENSIONS = set(['csv']) #限制上传文件格式
LOG_LEVEL = logging.WARNING LOG_LEVEL = logging.WARNING
LOG_FOLDER = 'logs/smart.log' LOG_FOLDER = 'logs/smart.log'
DEFAULT_COLOR = 'green'
\ No newline at end of file \ No newline at end of file
DEFAULT_COLOR = 'green'
TOWER_CUSTCONTROL = False
\ No newline at end of file \ No newline at end of file
此文件的差异太大,无法显示。
<?xml version="1.0" encoding="UTF-8"?>
<config ver="10">
<item key="ipstart" ver="10" value="192.168.101.75" />
<item key="ipend" ver="10" value="75" />
</config>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<config ver="10">
<item key="ipstart" ver="10" value="192.168.101.140" />
<item key="ipend" ver="10" value="141" />
</config>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>
\ No newline at end of file \ No newline at end of file
此文件的差异太大,无法显示。
此文件的差异太大,无法显示。
此文件太大,无法显示。
from flask import Flask
from flask_babel import Babel
from config import Config
import logging
from logging.handlers import RotatingFileHandler,TimedRotatingFileHandler
# from flask_socketio import SocketIO
is_start=False
def setup_log():
# 设置日志的记录等级
logging.basicConfig(level=Config.LOG_LEVEL) # 调试debug级
# 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
file_log_handler = RotatingFileHandler(Config.LOG_FOLDER, maxBytes=1024 * 1024 * 100, backupCount=10)
# 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息
# log_file_handler = TimedRotatingFileHandler(filename='logs/smartshelf.log', when="D", interval=1, backupCount=3)
formatter = logging.Formatter('%(asctime)s : %(message)s')
# 为刚创建的日志记录器设置日志记录格式
file_log_handler.setFormatter(formatter)
# 为全局的日志工具对象(flask app使用的)添加日志记录器
logging.getLogger().addHandler(file_log_handler)
setup_log()
app = Flask(__name__)
babel = Babel(app)
app.config.from_object(Config)
LANGUAGES = {
"zh": "Chinese",
"en": "English",
"ja": "Japanese"
}
@babel.localeselector
def get_locale():
return request.accept_languages.best_match(LANGUAGES.keys())
from app import config_ip,routes,post,led_strip,driver_gpio,autoback,qr_code
# return app
import requests
import threading
import time
def s():
data = {'key1':'value1','key2':'value2'}
time.sleep(2)
requests.post("http://127.0.0.1:5000/stoppost",data)
#if testCidExists():
time.sleep(2)
requests.post("http://127.0.0.1:5000/startpost",data)
logging.warning("启动完成")
t =threading.Thread(target=s)
t.start()
\ No newline at end of file \ No newline at end of file
[python: **.py]
[jinja2: **/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_
\ No newline at end of file \ No newline at end of file
import os
from flask import Flask, render_template, request, Response
from app import app
import time
from threading import Thread
#app = Flask(__name__)
@app.route('/ipconfig')
def shelfconfigA():
print("begin ip flask")
return render_template('ipconfig.html')
def Config_DHCP():
with open('/etc/dhcpcd.conf.bak', 'r') as f:
file_lines = f.readlines()
f.close()
with open('/etc/dhcpcd.conf', 'w') as f:
# for line in file_lines:
f.writelines(file_lines)
f.flush()
f.close()
def Config_StaticIP(IPAddress, Router_IP):
with open('/etc/dhcpcd.conf.bak', 'r') as f:
file_lines = f.readlines()
f.close()
with open('/etc/dhcpcd.conf', 'w') as f:
# for line in file_lines:
f.writelines(file_lines)
# f.write("static ip_address=" + str(request.args.get('new_ip')))
# interface eth0
#IPAddress = str(request.args.get('new_ip')
#Router_IP = str(request.args.get('new_ip')
f.write("interface eth0" + "\n")
if len(IPAddress) > 0:
f.write("static ip_address=" + IPAddress + "\n")
if len(Router_IP) > 0:
f.write("static routers=" + Router_IP + "\n")
# f.write("")
f.flush()
f.close()
def reboot_after_delay():
# Wait for 5 seconds before rebooting
time.sleep(5)
os.system('sudo reboot')
def Reenable_NetworkService():
#os.system('sudo systemctl stop networking')
#os.system('sudo systemctl start networking')
#os.system('sudo systemctl stop dhcpcd.service')
#print("services stop")
#os.system('sudo ip addr flush dev eth0')
#os.system('sudo systemctl start dhcpcd.service')
# Wait for 3 seconds before rebooting
reboot_thread = Thread(target=reboot_after_delay)
reboot_thread.start()
return "Apply Successfully, System will reboot in 5 seconds"
#return "Raspberry Pi will reboot in 3 seconds"
#os.system('sudo reboot')
def netmask_to_length(netmask):
# Convert the netmask to a list of integers
netmask = [int(x) for x in netmask.split(".")]
# Count the number of set bits in the netmask
length = 0
for octet in netmask:
while octet > 0:
length += octet & 1
octet >>= 1
return length
@app.route('/ip_config',methods=['POST'])
def IP_Config():
dhcp_enabled = request.form.get('dhcp')
if dhcp_enabled:
Config_DHCP()
print("DHCP ENABLED")
else:
IP_ADDR = str(request.form.get('new_ip'))
print("input:",str(request.form.get('new_ip')))
Router_ADDR = str(request.form.get('router_ip'))
NET_MASK = str(request.form.get('new_mask'))
IP_ADDR +="/"+str(netmask_to_length(NET_MASK))
print(IP_ADDR)
print(Router_ADDR)
Config_StaticIP(IP_ADDR,Router_ADDR)
print(IP_ADDR,Router_ADDR)
print("IP CHANGED")
#Reenable_NetworkService()
#Response('Apply Successfully', status=200, mimetype='text/plain')
return Reenable_NetworkService()
#return #'Apply Successfully ' #{} with DHCP enabled: {}'.format(IP_ADDR, 'True' if dhcp_enabled else 'False')
#Config_StaticIP("192.168.1.59/24", "192.168.1.1")
#Reenable_NetworkService()
import os
if os.name is not 'nt':
import RPi.GPIO as GPIO
import time
def init(gpiox):
GPIO.setmode(GPIO.BCM)
GPIO.setup(gpiox,GPIO.OUT)
def gpio_high(gpiox):
GPIO.output(gpiox, GPIO.HIGH)
def gpio_low(gpiox):
GPIO.output(gpiox, GPIO.LOW)
def clean():
GPIO.cleanup()
else:
def init(gpiox):
print(gpiox)
def gpio_high(gpiox):
print(gpiox)
def gpio_low(gpiox):
print(gpiox)
def clean():
print("clean")
\ No newline at end of file \ No newline at end of file
# Translations template for PROJECT.
# Copyright (C) 2022 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-05-11 16:02+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: post.py:290
msgid "关闭成功"
msgstr ""
#: post.py:293
msgid "无需关闭"
msgstr ""
#: post.py:397
msgid "未进行测试动作"
msgstr ""
#: routes.py:53 routes.py:382
msgid "加载成功"
msgstr ""
#: routes.py:56
msgid "加载失败,请在配置页面上传配置文件"
msgstr ""
#: routes.py:139 templates/ledtest.html:30 templates/ledtest.html:86
msgid "通道"
msgstr ""
#: routes.py:139
msgid "状态灯"
msgstr ""
#: routes.py:246
msgid "灯地址:{},已点亮"
msgstr ""
#: routes.py:292
msgid "灯地址:{},已关闭"
msgstr ""
#: routes.py:306
msgid "灯条已重置"
msgstr ""
#: routes.py:386
msgid "重新加载失败,请在配置页面上传配置文件"
msgstr ""
#: routes.py:421
msgid "灯条:{},颜色:{},已开启"
msgstr ""
#: routes.py:437
msgid "灯条:{}已关闭"
msgstr ""
#: templates/base.html:6 templates/ledtest.html:6 templates/shelfconfig.html:6
msgid "智能料架系统"
msgstr ""
#: templates/base.html:25 templates/ledtest.html:22
#: templates/shelfconfig.html:78
msgid "料架系统"
msgstr ""
#: templates/base.html:30
msgid "开关"
msgstr ""
#: templates/base.html:33
msgid "启动"
msgstr ""
#: templates/base.html:34
msgid "停止"
msgstr ""
#: templates/base.html:42 templates/ledtest.html:136
#: templates/shelfconfig.html:132
msgid "提醒消息"
msgstr ""
#: templates/base.html:47 templates/ledtest.html:141
#: templates/shelfconfig.html:137
msgid "运行状态"
msgstr ""
#: templates/base.html:52 templates/ledtest.html:151
#: templates/shelfconfig.html:142
msgid "配置文件加载状态"
msgstr ""
#: templates/base.html:57 templates/shelfconfig.html:101
#: templates/shelfconfig.html:147
msgid "服务器地址"
msgstr ""
#: templates/base.html:62 templates/shelfconfig.html:107
#: templates/shelfconfig.html:152
msgid "料架编号"
msgstr ""
#: templates/base.html:67
msgid "服务器连接状态"
msgstr ""
#: templates/base.html:76 templates/ledtest.html:130
#: templates/shelfconfig.html:126
msgid "运行日志&状态信息"
msgstr ""
#: templates/base.html:81
msgid "日志下载"
msgstr ""
#: templates/base.html:84
msgid "下载日志"
msgstr ""
#: templates/base.html:91
msgid "日志"
msgstr ""
#: templates/base.html:118 templates/base.html:142 templates/base.html:165
#: templates/ledtest.html:197 templates/ledtest.html:209
#: templates/shelfconfig.html:181 templates/shelfconfig.html:262
msgid "运行中"
msgstr ""
#: templates/base.html:119 templates/base.html:143 templates/base.html:166
#: templates/ledtest.html:198 templates/shelfconfig.html:263
msgid "已关闭"
msgstr ""
#: templates/base.html:120 templates/base.html:144 templates/base.html:167
#: templates/ledtest.html:199 templates/shelfconfig.html:264
msgid "未初始化"
msgstr ""
#: templates/base.html:125
msgid "启动失败"
msgstr ""
#: templates/base.html:149
msgid "停止失败"
msgstr ""
#: templates/base.html:173 templates/ledtest.html:204
#: templates/shelfconfig.html:273
msgid "未获取到状态信息"
msgstr ""
#: templates/head.html:29
msgid "亮灯料架"
msgstr ""
#: templates/head.html:33
msgid "控制"
msgstr ""
#: templates/head.html:34
msgid "测试"
msgstr ""
#: templates/head.html:35
msgid "料架配置"
msgstr ""
#: templates/ledtest.html:27
msgid "灯条测试"
msgstr ""
#: templates/ledtest.html:37 templates/ledtest.html:65
#: templates/ledtest.html:93
msgid "颜色"
msgstr ""
#: templates/ledtest.html:47
msgid "灯条全开"
msgstr ""
#: templates/ledtest.html:48
msgid "灯条关闭"
msgstr ""
#: templates/ledtest.html:54
msgid "库位操作测试"
msgstr ""
#: templates/ledtest.html:57
msgid "库位"
msgstr ""
#: templates/ledtest.html:75 templates/ledtest.html:102
msgid "亮灯"
msgstr ""
#: templates/ledtest.html:76 templates/ledtest.html:103
msgid "灭灯"
msgstr ""
#: templates/ledtest.html:77
msgid "重置"
msgstr ""
#: templates/ledtest.html:83
msgid "状态灯测试"
msgstr ""
#: templates/ledtest.html:110
msgid "下载库位二维码"
msgstr ""
#: templates/ledtest.html:122
msgid "下载二维码"
msgstr ""
#: templates/ledtest.html:124
msgid "单个二维码尺寸(含白色底框)尺寸为16*16mm,黑码尺寸为10*10mm"
msgstr ""
#: templates/ledtest.html:146
msgid "测试消息"
msgstr ""
#: templates/ledtest.html:210 templates/shelfconfig.html:182
msgid "料架运行中,请关闭后再进行测试"
msgstr ""
#: templates/shelfconfig.html:83
msgid "配置文件"
msgstr ""
#: templates/shelfconfig.html:87
msgid "选择文件"
msgstr ""
#: templates/shelfconfig.html:90
msgid "上传"
msgstr ""
#: templates/shelfconfig.html:96
msgid "服务器配置"
msgstr ""
#: templates/shelfconfig.html:102
msgid "请填入服务器地址"
msgstr ""
#: templates/shelfconfig.html:108
msgid "请填入料架编号"
msgstr ""
#: templates/shelfconfig.html:111
msgid "保存"
msgstr ""
#: templates/shelfconfig.html:116
msgid "控制器备份&升级"
msgstr ""
#: templates/shelfconfig.html:120
msgid "料架升级"
msgstr ""
#: templates/shelfconfig.html:121
msgid "teamview"
msgstr ""
#: templates/shelfconfig.html:157
msgid "操作提醒"
msgstr ""
#: templates/shelfconfig.html:162
msgid "软件版本"
msgstr ""
#: templates/shelfconfig.html:192
msgid "请选择文件"
msgstr ""
#: templates/shelfconfig.html:196
msgid "文件限制最大"
msgstr ""
#: templates/shelfconfig.html:212
msgid "上传完成!"
msgstr ""
#: templates/shelfconfig.html:215
msgid "上传失败!"
msgstr ""
#: templates/shelfconfig.html:228
msgid "不能提交空数据"
msgstr ""
#: templates/shelfconfig.html:240
msgid "保存成功"
msgstr ""
#: templates/shelfconfig.html:280
msgid "检查并升级最新最新版本"
msgstr ""
#: templates/shelfconfig.html:292 templates/shelfconfig.html:314
msgid "升级成功,请刷新浏览器"
msgstr ""
#: templates/shelfconfig.html:297 templates/shelfconfig.html:319
msgid "已取消"
msgstr ""
#: templates/shelfconfig.html:302
msgid "确认打开"
msgstr ""
import os
import sys
import qrcode
# from PIL import Image
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import numpy
from app import app
from flask import jsonify,render_template,request,send_from_directory
import matplotlib.font_manager as fm
import logging
code_path = '/prog/smartshelf/app/static/uploads'
def make_qrcode(file_code):
# for line in all_data:
# A_NUMBER = line[0]
# c_start = int(line[1])
# c_stop = int(line[2])
# dirs_str = deal_line_code(project_number,A_NUMBER,c_start,c_stop)
# resize(project_number,dirs_str)
# current_path_file=os.path.join(code_path,t_file)
qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=0)
qr.add_data(file_code)
qr.make(fit=True)
img = qr.make_image()
file = "{}/{}.png".format(code_path,file_code)
img.save(file)
# img1.save("./{}_qr_jpg/{}/{}.jpg".format(project_number,dirs_str,filename[:-4]))
return True
def resize(file_code):
# path = './{}_qr_png/{}'.format(project_number,dirs_str)
# path_list = os.listdir(path)
img1 = Image.open("{}/{}.png".format(code_path,file_code))
# img1 = Image.open("E:/qr_png/code/0/{}.png".format(filename))
img1 = img1.resize((300, 300),Image.ANTIALIAS)
# print (filename[:-4])
img1.save("{}/{}.jpg".format(code_path,file_code))
def deal_number(file_code):
print (file_code)
color = "White"
img_str = Image.new("RGB",(480,90),color)
img_str.save("{}/temp_number.jpg".format(code_path))
im = Image.open("{}/temp_number.jpg".format(code_path))
# font = ImageFont.truetype('simsun.ttc',55)
# font = ImageFont.truetype(fm.findfont(fm.FontProperties(family='DejaVu Sans')),63)
if os.path.isfile("/usr/share/fonts/truetype/dejavu/simsun.ttf"):
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/simsun.ttf",75)
draw = ImageDraw.Draw(im)
draw.text((50,20), file_code, font=font, fill='#000')
else:
font = ImageFont.truetype(fm.findfont(fm.FontProperties(family='DejaVu Sans')),75)
draw = ImageDraw.Draw(im)
draw.text((30,20), file_code, font=font, fill='#000')
# draw.text((60,13), filename, font=font, fill='#000') #602项目改动
im.save("{}/temp_number.jpg".format(code_path))
def paste(file_code):
color = 'white'
target = Image.new("RGB",(300,390),color)
# qr = Image.open("E:/qr_png/jpg_code/B/{}".format(filename))
# qr = Image.open("E:/code_tool/{}/{}/{}.jpg".format(source_path,path_str,filename))
qr = Image.open('{}/{}.jpg'.format(code_path,file_code))
im = Image.open('{}/temp_number.jpg'.format(code_path))
a = 0 # 图片距离左边的大小
b = 0 # 图片距离上边的大小
c = 300 # 图片距离左边的大小 + 图片自身宽度
d = 300 # 图片距离上边的大小 + 图片自身高度
target.paste(qr, (a, b, c, d))
e = 0
f = 300
# target.paste(im, (e, f))
target.save("{}/code_img_str.jpg".format(code_path))
targeta = Image.new("RGB",(480,480),color)
targetb = Image.open("{}/code_img_str.jpg".format(code_path))
targeta.paste(targetb, (90, 60))
targeta.paste(im, (0, 360))
targeta.save("{}/{}.jpg".format(code_path,file_code))
logging.warning("库位二维码生成成功:{}".format(file_code))
@app.route('/downqrcode/', methods=['GET','POST'], strict_slashes=False)
def downqrcode():
# file_code = '001-01-001'
file_code = str(request.args.get("code"))
make_qrcode(file_code)
resize(file_code)
deal_number(file_code)
paste(file_code)
c_path = '/prog/smartshelf/app/static/uploads/'
filename = '{}.jpg'.format(file_code)
if request.method == "GET":
if os.path.isfile(os.path.join(c_path, filename)):
return send_from_directory(c_path, filename, as_attachment=True)
\ No newline at end of file \ No newline at end of file
/*
* Globals
*/
/* Links */
a,
a:focus,
a:hover {
color: #fff;
}
/* Custom default button */
.btn-default,
.btn-default:hover,
.btn-default:focus {
color: #333;
text-shadow: none; /* Prevent inheritance from `body` */
background-color: #fff;
border: 1px solid #fff;
}
/*
* Base structure
*/
html,
body {
height: 100%;
background-color: #333;
}
body {
color: #fff;
text-align: center;
text-shadow: 0 1px 3px rgba(0,0,0,.5);
}
/* Extra markup and styles for table-esque vertical and horizontal centering */
.site-wrapper {
display: table;
width: 100%;
height: 100%; /* For at least Firefox */
min-height: 100%;
-webkit-box-shadow: inset 0 0 100px rgba(0,0,0,.5);
box-shadow: inset 0 0 100px rgba(0,0,0,.5);
}
.site-wrapper-inner {
display: table-cell;
vertical-align: top;
}
.cover-container {
margin-right: auto;
margin-left: auto;
}
/* Padding for spacing */
.inner {
padding: 30px;
}
/*
* Header
*/
.masthead-brand {
margin-top: 10px;
margin-bottom: 10px;
}
.masthead-nav > li {
display: inline-block;
}
.masthead-nav > li + li {
margin-left: 20px;
}
.masthead-nav > li > a {
padding-right: 0;
padding-left: 0;
font-size: 16px;
font-weight: bold;
color: #fff; /* IE8 proofing */
color: rgba(255,255,255,.75);
border-bottom: 2px solid transparent;
}
.masthead-nav > li > a:hover,
.masthead-nav > li > a:focus {
background-color: transparent;
border-bottom-color: #a9a9a9;
border-bottom-color: rgba(255,255,255,.25);
}
.masthead-nav > .active > a,
.masthead-nav > .active > a:hover,
.masthead-nav > .active > a:focus {
color: #fff;
border-bottom-color: #fff;
}
@media (min-width: 768px) {
.masthead-brand {
float: left;
}
.masthead-nav {
float: right;
}
}
/*
* Cover
*/
.cover {
padding: 0 20px;
}
.cover .btn-lg {
padding: 10px 20px;
font-weight: bold;
}
/*
* Footer
*/
.mastfoot {
color: #999; /* IE8 proofing */
color: rgba(255,255,255,.5);
}
/*
* Affix and center
*/
@media (min-width: 768px) {
/* Pull out the header and footer */
.masthead {
position: fixed;
top: 0;
}
.mastfoot {
position: fixed;
bottom: 0;
}
/* Start the vertical centering */
.site-wrapper-inner {
vertical-align: middle;
}
/* Handle the widths */
.masthead,
.mastfoot,
.cover-container {
width: 100%; /* Must be percentage or pixels for horizontal alignment */
}
}
@media (min-width: 992px) {
.masthead,
.mastfoot,
.cover-container {
width: 700px;
}
}
/*!
* IE10 viewport hack for Surface/desktop Windows 8 bug
* Copyright 2014-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
/*
* See the Getting Started docs for more information:
* http://getbootstrap.com/getting-started/#support-ie10-width
*/
@-ms-viewport { width: device-width; }
@-o-viewport { width: device-width; }
@viewport { width: device-width; }
/*!
* IE10 viewport hack for Surface/desktop Windows 8 bug
* Copyright 2014-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
// See the Getting Started docs for more information:
// http://getbootstrap.com/getting-started/#support-ie10-width
(function () {
'use strict';
if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
var msViewportStyle = document.createElement('style')
msViewportStyle.appendChild(
document.createTextNode(
'@-ms-viewport{width:auto!important}'
)
)
document.querySelector('head').appendChild(msViewportStyle)
}
})();
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')
\ No newline at end of file \ No newline at end of file
<span style="font-size:18px;"><!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>{{ _('智能料架系统') }}</title>
<!-- <link rel="icon" href="/static/favicon.ico"> -->
<!-- <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"> -->
<link rel="icon" href="/static/favicon.ico">
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</head>
<body>
{% set index=1 %}
{% import 'head.html' as head with context%}
{{ head }}
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<h2>{{ _('料架系统') }}</h2>
<hr class="divider">
<!-- 料架启动关闭 -->
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">{{ _('开关') }}</h3>
</div>
<div class="panel-body">
<input type="button" value={{ _('启动') }} class="btn btn-info" onclick="startpost()"/>
<input type="button" value={{ _('停止') }} class="btn btn-warning" onclick="stoppost()"/>
</div>
</div>
<div id="panel-group">
<!-- 1 -->
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">{{ _('提醒消息') }}</h3>
</div>
<div class="panel-body">
<div class="alert alert-info" role="alert">
<p>
{{ _('运行状态') }}:<span id="shelfstate"></span>
</p>
</div>
<div class="alert alert-info" role="alert">
<p>
{{ _('配置文件加载状态') }}:<span id="testinfo">{{ _('加载成功') if config_state else _('加载失败,请在配置页面上传配置文件') }}</span>
</p>
</div>
<div class="alert alert-info" role="alert">
<p>
{{ _('服务器地址') }}:<span id="ipconfig"></span>
</p>
</div>
<div class="alert alert-info" role="alert">
<p>
{{ _('料架编号') }}:<span id="ccid"></span>
</p>
</div>
<div class="alert alert-info" role="alert">
<p>
{{ _('服务器连接状态') }}:<span id="poststate"></span>
</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<h2>{{ _('运行日志&状态信息') }}</h2>
<hr class="divider">
<!-- 日志下载 -->
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">{{ _('日志下载') }}</h3>
</div>
<div class="panel-body">
<a type="button" class="btn btn-warning" href="{{ url_for('download') }}">{{ _('下载日志') }}</a>
</div>
</div>
<!-- 日志显示 -->
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">{{ _('日志') }}</h3>
</div>
<div class="panel-body">
<div id="logmsg" style="overflow:auto;height: 400px;background:#000; color:green"></div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
getstate();
taillog();
console.log('success');
});
function startpost(){
$.ajax({
url:"/startpost",
type:"post",
// data:form,
dataType: 'json',
processData:false,
contentType:false,
success:function(data){
if (data[0].state == 'on') {$("#shelfstate").html("{{ _('运行中') }}");}
else if (data[0].state == 'off') {$("#shelfstate").html("{{ _('已关闭') }}");}
else {$("#shelfstate").html("{{ _('未初始化') }}");}
// console.log(data)
alert (data[0].msg)
},
error:function(e){
alert("{{ _('启动失败') }}");
}
})
}
function stoppost(){
// var form= new FormData(document.getElementById("test_form"));
var shelfstate = document.getElementById("shelfstate").value
console.log(shelfstate)
$.ajax({
url:"/stoppost",
type:"post",
// data:form,
dataType: 'json',
processData:false,
contentType:false,
success:function(data){
if (data[0].state == 'on') {$("#shelfstate").html("{{ _('运行中') }}");}
else if (data[0].state == 'off') {$("#shelfstate").html("{{ _('已关闭') }}");}
else {$("#shelfstate").html("{{ _('未初始化') }}");}
console.log(data)
alert (data[0].msg)
},
error:function(e){
alert("{{ _('停止失败') }}");
}
})
}
// 获取开机关机状态
function getstate(){
// var form= new FormData(document.getElementById("test_form"));
$.ajax({
url:"/getstate",
type:"post",
// data:form,
dataType: 'json',
processData:false,
contentType:false,
success:function(data){
console.log(data)
if (data[0].state == 'on') {$("#shelfstate").html("{{ _('运行中') }}");}
else if (data[0].state == 'off') {$("#shelfstate").html("{{ _('已关闭') }}");}
else {$("#shelfstate").html("{{ _('未初始化') }}");}
// $("#gpioconfig").html(data[0].gpio)
$("#ipconfig").html(data[0].ipconfig['ip'])
$("#ccid").html(data[0].ipconfig['cid'])
},
error:function(e){
alert("{{ _('未获取到状态信息') }}");
}
})
}
// 获取开机关机状态
function taillog(){
// var form= new FormData(document.getElementById("test_form"));
$.ajax({
url:"/taillog",
type:"post",
// data:form,
dataType: 'json',
processData:false,
contentType:false,
success:function(data){
$("#logmsg").html(data.msg)
$("#poststate").html(data.poststate)
},
error:function(e){
}
})
}
setInterval(function(){
taillog();
}, 3000);
</script>
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</body>
</html>
\ No newline at end of file \ No newline at end of file
<script>
function switchLanguage(language) {
$.ajax({
url: "/language/" + language,
type: "get",
//data: JSON.stringify(ionum),
//contentType: "application/json",
//dataType: 'json',
success: function (data) {
location.reload();
},
error: function (e) {
window.reload();
}
});
return false;
}
</script>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">{{ _('亮灯料架') }}</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li{{ " class=active" if index==1 }}><a href="{{ url_for('index') }}">{{ _('控制') }}</a></li>
<li{{ " class=active" if index==2 }}><a href="{{ url_for('ledtest') }}">{{ _('测试') }}</a> </li>
<li{{ " class=active" if index==3 }}><a href="{{ url_for('shelfconfig') }}">{{ _('料架配置') }}</a></li>
</ul>
<ul class="nav navbar-nav navbar-right" style="font-size: 14px;"">
<li><a href=" #" onclick="return switchLanguage('zh');">简体中文</a></li>
<li><a href="#" onclick="return switchLanguage('en');">English</a></li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</nav>
<div style="clear:both;"></div>
\ No newline at end of file \ No newline at end of file
# English translations for PROJECT.
# Copyright (C) 2021 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-05-11 16:02+0800\n"
"PO-Revision-Date: 2021-04-08 16:25+0800\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n"
"Language-Team: en <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: post.py:290
msgid "关闭成功"
msgstr "Closed successfully"
#: post.py:293
msgid "无需关闭"
msgstr "No need to close"
#: post.py:397
msgid "未进行测试动作"
msgstr "No test action"
#: routes.py:53 routes.py:382
msgid "加载成功"
msgstr "Loading succeeded"
#: routes.py:56
msgid "加载失败,请在配置页面上传配置文件"
msgstr ""
"Loading failed, please upload the configuration file on the configuration"
" page"
#: routes.py:139 templates/ledtest.html:30 templates/ledtest.html:86
msgid "通道"
msgstr "Channel"
#: routes.py:139
msgid "状态灯"
msgstr "Status light test"
#: routes.py:246
msgid "灯地址:{},已点亮"
msgstr ""
#: routes.py:292
msgid "灯地址:{},已关闭"
msgstr "Light address: {}, off"
#: routes.py:306
msgid "灯条已重置"
msgstr "Light bar reset"
#: routes.py:386
msgid "重新加载失败,请在配置页面上传配置文件"
msgstr ""
"Reload failed, please upload the configuration file on the configuration "
"page"
#: routes.py:421
msgid "灯条:{},颜色:{},已开启"
msgstr "Light bar: {}, color: {}, turned on"
#: routes.py:437
msgid "灯条:{}已关闭"
msgstr "Light bar: {} turned off"
#: templates/base.html:6 templates/ledtest.html:6 templates/shelfconfig.html:6
msgid "智能料架系统"
msgstr "SmartShelf"
#: templates/base.html:25 templates/ledtest.html:22
#: templates/shelfconfig.html:78
msgid "料架系统"
msgstr "Material rack system"
#: templates/base.html:30
msgid "开关"
msgstr "switch"
#: templates/base.html:33
msgid "启动"
msgstr "Start"
#: templates/base.html:34
msgid "停止"
msgstr "Stop"
#: templates/base.html:42 templates/ledtest.html:136
#: templates/shelfconfig.html:132
msgid "提醒消息"
msgstr "Reminder message"
#: templates/base.html:47 templates/ledtest.html:141
#: templates/shelfconfig.html:137
msgid "运行状态"
msgstr "Running status"
#: templates/base.html:52 templates/ledtest.html:151
#: templates/shelfconfig.html:142
msgid "配置文件加载状态"
msgstr "Configuration file loading status"
#: templates/base.html:57 templates/shelfconfig.html:101
#: templates/shelfconfig.html:147
msgid "服务器地址"
msgstr "Server address"
#: templates/base.html:62 templates/shelfconfig.html:107
#: templates/shelfconfig.html:152
msgid "料架编号"
msgstr "Material rack number"
#: templates/base.html:67
msgid "服务器连接状态"
msgstr "Server connection status"
#: templates/base.html:76 templates/ledtest.html:130
#: templates/shelfconfig.html:126
msgid "运行日志&状态信息"
msgstr "Run log & status information"
#: templates/base.html:81
msgid "日志下载"
msgstr "Log"
#: templates/base.html:84
msgid "下载日志"
msgstr "Download log"
#: templates/base.html:91
msgid "日志"
msgstr "Running log"
#: templates/base.html:118 templates/base.html:142 templates/base.html:165
#: templates/ledtest.html:197 templates/ledtest.html:209
#: templates/shelfconfig.html:181 templates/shelfconfig.html:262
msgid "运行中"
msgstr "Running"
#: templates/base.html:119 templates/base.html:143 templates/base.html:166
#: templates/ledtest.html:198 templates/shelfconfig.html:263
msgid "已关闭"
msgstr "Closed"
#: templates/base.html:120 templates/base.html:144 templates/base.html:167
#: templates/ledtest.html:199 templates/shelfconfig.html:264
msgid "未初始化"
msgstr "Uninitialized"
#: templates/base.html:125
msgid "启动失败"
msgstr "Start failed"
#: templates/base.html:149
msgid "停止失败"
msgstr "Stop failed"
#: templates/base.html:173 templates/ledtest.html:204
#: templates/shelfconfig.html:273
msgid "未获取到状态信息"
msgstr "No status information was obtained"
#: templates/head.html:29
msgid "亮灯料架"
msgstr "Lighting material rack"
#: templates/head.html:33
msgid "控制"
msgstr "Control"
#: templates/head.html:34
msgid "测试"
msgstr "Test"
#: templates/head.html:35
msgid "料架配置"
msgstr "Material rack configuration"
#: templates/ledtest.html:27
msgid "灯条测试"
msgstr "Light bar test"
#: templates/ledtest.html:37 templates/ledtest.html:65
#: templates/ledtest.html:93
msgid "颜色"
msgstr "color"
#: templates/ledtest.html:47
msgid "灯条全开"
msgstr "light"
#: templates/ledtest.html:48
msgid "灯条关闭"
msgstr "off"
#: templates/ledtest.html:54
msgid "库位操作测试"
msgstr "Location operation test"
#: templates/ledtest.html:57
msgid "库位"
msgstr "Location"
#: templates/ledtest.html:75 templates/ledtest.html:102
msgid "亮灯"
msgstr "On"
#: templates/ledtest.html:76 templates/ledtest.html:103
msgid "灭灯"
msgstr "Off"
#: templates/ledtest.html:77
msgid "重置"
msgstr "Reset"
#: templates/ledtest.html:83
msgid "状态灯测试"
msgstr "Status light test"
#: templates/ledtest.html:110
msgid "下载库位二维码"
msgstr "Download location QR code"
#: templates/ledtest.html:122
msgid "下载二维码"
msgstr "Download QR code"
#: templates/ledtest.html:124
msgid "单个二维码尺寸(含白色底框)尺寸为16*16mm,黑码尺寸为10*10mm"
msgstr ""
"Single QR code size(including white bottom frame) size is 16*16mm,black "
"code size is 10*10mm"
#: templates/ledtest.html:146
msgid "测试消息"
msgstr "Test message"
#: templates/ledtest.html:210 templates/shelfconfig.html:182
msgid "料架运行中,请关闭后再进行测试"
msgstr "When the material rack is running, please stop it before testing"
#: templates/shelfconfig.html:83
msgid "配置文件"
msgstr "Config file"
#: templates/shelfconfig.html:87
msgid "选择文件"
msgstr "Select file"
#: templates/shelfconfig.html:90
msgid "上传"
msgstr "Upload"
#: templates/shelfconfig.html:96
msgid "服务器配置"
msgstr "Server configuration"
#: templates/shelfconfig.html:102
msgid "请填入服务器地址"
msgstr "Server address"
#: templates/shelfconfig.html:108
msgid "请填入料架编号"
msgstr "Material rack number"
#: templates/shelfconfig.html:111
msgid "保存"
msgstr "Save"
#: templates/shelfconfig.html:116
msgid "控制器备份&升级"
msgstr "Controller backup & upgrade"
#: templates/shelfconfig.html:120
msgid "料架升级"
msgstr "Software upgrade"
#: templates/shelfconfig.html:121
msgid "teamview"
msgstr ""
#: templates/shelfconfig.html:157
msgid "操作提醒"
msgstr "Operation reminder"
#: templates/shelfconfig.html:162
msgid "软件版本"
msgstr "Software version"
#: templates/shelfconfig.html:192
msgid "请选择文件"
msgstr "Select file"
#: templates/shelfconfig.html:196
msgid "文件限制最大"
msgstr "Maximum file limit"
#: templates/shelfconfig.html:212
msgid "上传完成!"
msgstr "Upload complete"
#: templates/shelfconfig.html:215
msgid "上传失败!"
msgstr "上传失败"
#: templates/shelfconfig.html:228
msgid "不能提交空数据"
msgstr "Cannot submit empty data"
#: templates/shelfconfig.html:240
msgid "保存成功"
msgstr "Saved successfully"
#: templates/shelfconfig.html:280
msgid "检查并升级最新最新版本"
msgstr "Check and upgrade the latest version"
#: templates/shelfconfig.html:292 templates/shelfconfig.html:314
msgid "升级成功,请刷新浏览器"
msgstr "Upgrade succeeded, please refresh the browser"
#: templates/shelfconfig.html:297 templates/shelfconfig.html:319
msgid "已取消"
msgstr "Cancelled"
#: templates/shelfconfig.html:302
msgid "确认打开"
msgstr "Confirm open"
1.52
\ No newline at end of file \ No newline at end of file
import os
import logging
# from dotenv import load_dotenv
basedir = os.path.abspath(os.path.dirname(__file__))
# load_dotenv(os.path.join(basedir, '.env'))
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'app.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
URL = 'http://192.168.1.100:8080/service/store/communication'
UPLOAD_FOLDER = '/static/uploads'
STATE_PATH = '/state/'
ALLOWED_EXTENSIONS = set(['csv']) #限制上传文件格式
LOG_LEVEL = logging.WARNING
LOG_FOLDER = 'logs/smart.log'
DEFAULT_COLOR = 'green'
\ No newline at end of file \ No newline at end of file
from app import app,db
from app.models import State
@app.shell_context_processor
def make_shell_context():
return {'db': db, 'State': State}
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<config ver="10">
<item key="ipstart" ver="10" value="192.168.101.125" />
<item key="ipend" ver="10" value="125" />
</config>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<config ver="10">
<item key="ipstart" ver="10" value="192.168.101.125" />
<item key="ipend" ver="10" value="125" />
</config>
\ No newline at end of file \ No newline at end of file
此文件类型无法预览
...@@ -156,6 +156,12 @@ ...@@ -156,6 +156,12 @@
<param name="key"></param> <param name="key"></param>
<param name="value"></param> <param name="value"></param>
</member> </member>
<member name="M:ConfigHelper.Config.Del(System.String)">
<summary>
删除配置
</summary>
<param name="key"></param>
</member>
<member name="M:ConfigHelper.Config.SaveChangeDebounce"> <member name="M:ConfigHelper.Config.SaveChangeDebounce">
<summary> <summary>
保存设置 保存设置
...@@ -261,5 +267,68 @@ ...@@ -261,5 +267,68 @@
</summary> </summary>
<param name="comment"></param> <param name="comment"></param>
</member> </member>
<member name="T:CommonLib">
<summary>
程序公共类
</summary>
</member>
<member name="P:CommonLib.AppPathExe">
<summary>
程序exe全路经 如d:\app\app.exe
</summary>
</member>
<member name="P:CommonLib.AppPathDir">
<summary>
程序所在路径 如d:\app\
</summary>
</member>
<member name="P:CommonLib.AppPathRoot">
<summary>
程序所在盘符 如d:\
</summary>
</member>
<member name="P:CommonLib.AppName">
<summary>
程序exe名称
</summary>
</member>
<member name="P:CommonLib.AppAssemblyTitle">
<summary>
程序AssemblyTitle
</summary>
</member>
<member name="M:CommonLib.GetPath(System.String)">
<summary>
获取相对当前程序的目录
</summary>
<param name="dirname"></param>
<returns></returns>
</member>
<member name="M:CommonLib.RegisterInstall">
<summary>
将程序路径写到注册表, 方便以后做软件更新
</summary>
</member>
<member name="M:CommonLib.AddOrUpdateStartupTask(System.Boolean,System.Int32)">
<summary>
将程序设置为计划任务电脑开机,用户登陆后自动启动
</summary>
<param name="enable">是否启用</param>
<param name="delaysec">延迟启动时间秒</param>
</member>
<member name="M:CommonLib.AddTaskAction(System.Action)">
<summary>
添加需要每天定时运行的任务
</summary>
<param name="action"></param>
</member>
<member name="M:CommonLib.DeleteOverDayFile(System.String,System.String,System.Int32)">
<summary>
删除超过指定天数的文件
</summary>
<param name="path">文件路经</param>
<param name="ext">扩展名检索格式:*.jpg</param>
<param name="day">天数</param>
</member>
</members> </members>
</doc> </doc>
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup> </startup>
</configuration>
\ No newline at end of file \ No newline at end of file
</configuration>
此文件的差异太大,无法显示。
import pickle
import os
from enum import Enum, auto
import string
import logging
from config import Config
basepath = os.path.dirname(__file__)
shelfconfigfile = basepath + Config.STATE_PATH+'shelfconfig.pkl'
class LEDColorSort(Enum):
GRB = 1
RGB = 2
class _shelfconfig:
def __init__(self):
self.LED_ColorSort = LEDColorSort.RGB.value
self.LED_COUNT=1000
self.TOWER_CUSTCONTROL=0
def Save(self):
with open(shelfconfigfile, 'wb') as f:
pickle.dump(self, f)
shelfconfig:_shelfconfig
shelfconfig = _shelfconfig()
if os.path.exists(shelfconfigfile):
with open(shelfconfigfile, 'rb') as f:
a = pickle.load(f)
for it in a.__dict__.items():
if it[0].find('__')>=0 or it[0]=='Save':
continue
if shelfconfig.__dict__.get(it[0]) is not None:
shelfconfig.__dict__[it[0]]=a.__dict__[it[0]]
...@@ -5,10 +5,13 @@ config and init 24-LEDs-stripe ...@@ -5,10 +5,13 @@ config and init 24-LEDs-stripe
""" """
import os import os
import logging
from app.g import shelfconfig, LEDColorSort
from matplotlib.pyplot import cla from matplotlib.pyplot import cla
LED_COUNT = 1000 # 要控制LED的数量. LED_COUNT = 1000 # 要控制LED的数量.
#2400
#GRB
# LED_PIN = 18 # GPIO接口 (PWM编码). # LED_PIN = 18 # GPIO接口 (PWM编码).
LED_BRIGHTNESS = 100 # 设置LED亮度 (0-255) LED_BRIGHTNESS = 100 # 设置LED亮度 (0-255)
#以下LED配置无需修改 #以下LED配置无需修改
...@@ -26,11 +29,19 @@ if os.name != 'nt': ...@@ -26,11 +29,19 @@ if os.name != 'nt':
#Color=ColorA #Color=ColorA
def Color(red,green, blue, white=0): def Color(red,green, blue, white=0):
return ColorA(green,red,blue) if shelfconfig.LED_ColorSort == LEDColorSort.RGB.value:
return ColorA(red,green,blue)
else:
return ColorA(green,red,blue)
def get_strip(pin=12): def get_strip(pin=12):
LED_PIN = pin LED_PIN = pin
if stripStore.get(LED_PIN) is None: if stripStore.get(LED_PIN) is None:
LED_COUNT = shelfconfig.LED_COUNT
print('LED_COUNT:',str(LED_COUNT))
print('LED_ColorSort:',str(shelfconfig.LED_ColorSort))
logging.info('LED_COUNT:'+str(LED_COUNT))
logging.info('LED_ColorSort:'+str(shelfconfig.LED_ColorSort))
stripStore[LED_PIN] = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS,LED_CHANNEL) stripStore[LED_PIN] = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS,LED_CHANNEL)
stripStore[LED_PIN].begin() stripStore[LED_PIN].begin()
# Initialize the library (must be called once before other functions). # Initialize the library (must be called once before other functions).
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!