知识点
1.交换机
交换机发生在网络的第二层数据链路层,根据MAC地址寻址
路由器发生在第三层网络层。根据IP地址寻找下一个设备,可以处理TCPIP协议
交换机是分配网络数据,路由器可以给网络分配IP地址,分配给你地址而且可以随时通过地址过来找到你。
路由器可以在不同时间内把一个IP分配给多台主机使用。交换机是通过MAC地址和识别各个不同的主机。
POE (Power Over Ethernet) ,支持以太网供电的交换机。
2.内网和外网的区别
局域网(LAN)相对于广域网(WAN)而言,主要是指在小范围内的计算机互联网络。这个“小范围”可以是一个家庭,一所学校,一家公司,或者是一个政府部门。BT中常常提到的公网、外网,即广域网(WAN);BT中常常提到私网、内网,即局域网(LAN)
MAC地址(英语:Media Access Control Address),直译为媒体存取控制位址,也称为局域网地址(LAN Address),MAC位址,以太网地址(Ethernet Address)或物理地址(Physical Address),它是一个用来确认网络设备位置的位址。
3.六类网线,也就是符合CAT-6标准的线缆。
传输频率:250Mhz或更高
用 途:交换机、路由器到电脑的数据传输
传输速率:1000Mbps
RS-485线:联网通信接口
4.Jenkins:基于Java开发的一种持续集成工具,开源的
黑盒子(Blackbox):FPF 引擎(FPF_Engine) iot_id:黑盒子的标识
网关(Gateway):向上通过以太网与黑盒子用 mqtt 协议通讯,向下通过 RS-485 与精喂仪通讯;
ACK (Acknowledge character)即是确认字符,响应码,在数据通信中,接收站发给发送站的一种传输类控制字符。
6.'pip' 不是内部或外部命令,也不是可运行的程序
=》配环境变量
18.shortuuid
pip install shortuuid
>>> import shortuuid
>>> shortuuid.uuid()
'vytxeTZskVKR7C7WgdSP3d' # 22位
19.django-getenv
安装:
pip install django-getenv
使用:settings.py
from getenv import env
SECRET_KEY = env("SECRET_KEY", "a_secret_key")
20.python-dotenv
安装:
pip install python-dotenv==0.10.3
使用:
Assuming you have created the .env file along-side your settings module.
.
├── .env
└── settings.py
# .env
DATABASE_PASSWORD='mysql@123'
Add the following code to your settings.py:
import os
让 .env 文件支持中文注释
from dotenv import find_dotenv, load_dotenv
load_dotenv(find_dotenv(usecwd=True), override=True, encoding="utf8")
如果所开发的项目是主项目,建议使用明确的 .env 路径,使团队其他成员容易理解,如:
load_dotenv("./.env", override=True, encoding="utf8")
DATABASE_PASSWORD = os.getenv("DATABASE_PASSWORD")
21.simplejson
simplejson:Simple, fast, extensible JSON encoder/decoder for Python
安装simplejson
pip install simplejson
import simplejson
d= [{'a': 'bbb'}, {'c': 'ddd'}, {'e': 'fff'}]
r=simplejson.dumps(d,ensure_ascii=False)
print(r)
print(type(r))
# dump()和dumps(),dump是用于将内容转json字符串后写入文件中,dumps是将json格式的数据(字典或字典组成的列表)转换成json字符串。
# 在dumps对数据进行处理时,会做encoding(编码)操作,dumps()中的ensure_ascii默认是为True的,会将中文也编码成ascii,所以我们指定ensure_ascii=False。
s=simplejson.loads(r,encoding='utf-8',strict=False)
print(s)
print(type(s))
# load()和loads(),load与dump对应,是用于从文件中读取json字符串然后进行转换的,loads是将json字符串直接转换成Python数据类型。
# 在使用loads对json字符串进行转换时,有时候可能因为json字符串的格式不是完全的符合json格式,会造成loads报错,这时候我们可以设置参数strict=False,表示loads()时,不严格检查json格式。
22.把simple包(python-GatewayServiceCluster)拷到linux,用docker-compose方法启动,便安装了mysql、redis、mqtt
ouyangling@ŷ▒▒▒▒ MINGW64 /$ ssh root@172.20.6.196 -p 32200
用filezilla把包拷到linux
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster# ls
develop kafka-certificate readme.md simple-deployment
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster# cd simple-deployment/
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# ls
docker-compose.yaml docker_datas modify_network_config.sh reset_database.sh
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment#docker-compose up
Creating network "simpledeployment_default" with the default driver
Pulling mysql (ccr.ccs.tencentyun.com/dereck/mysql:5)...
ERROR: Get https://ccr.ccs.tencentyun.com/v2/dereck/mysql/manifests/5: unauthorized: autheation required # 进入容器需要用户/密码
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# sudo docker login --username=100008735620 --password=Ht141421 ccr.ccs.tencentyun.com
登陆/登出一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
登陆到Docker Hub:docker login -u 用户名 -p 密码 [SERVER]
登出Docker Hub:docker logout [SERVER]
Login Succeeded
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment#docker-compose up -d
gatewayservice python run.py gateway_service Up
mqtt_transfer_service python run.py mqtt_transfe ... Up
mysql Loading... mysqld Up 0.0.0.0:50006->3306/tcp, 3306
offline_service python run.py offline_service Up
redis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# docker-compose down # 停掉容器
Stopping debugapiservice ... done
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# docker-compose ps
Name Command State Ports
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment#vim docker-compose.yaml # 修改mysql端口
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# docker-compose up -d
Creating network "simpledeployment_default" with the default driver
Creating mysql ...
Creating emqttd ...
Creating redis ...
Creating mysql
Creating redis
Creating redis ... done
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# docker-compose logs -f emqttd # 查看实时日志
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# iptables --flush # 关闭防火墙
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment/docker_datas# chmod 777 -R emqttd/ # chmod能改变权限,-R是目录下所有文件,777就是高权限(读、写、执行) r读取:4, w写入:2 ,x执行:1
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment/docker_datas# ll
total 36
drwxrwxrwx 9 root root 4096 Mar 23 11:19 ./
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment/docker_datas# apt-get -f install
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment/docker_datas# apt update
apt update:只检查,不更新(已安装的软件包是否有可用的更新,给出汇总报告)
apt upgrade:更新已安装的软件包
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment/docker_datas# apt install unzip # 安装unzip包
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment/docker_datas# unzip emqttd.zip # 解压
History:
80 sudo docker login --username=100008735620 --password=Ht141421 ccr.ccs.tencentyun.com
81 docker-compose logs
82 docker-compose up -d
84 docker-compose down
86 vim docker-compose.yaml
90 docker-compose ps
91 history
23.在python-GatewayService装fpfdb/edgesdk依赖
如果是在一个应用项目(比如 GatewayService 中),边测试边开发fpfdb接口,按如下步骤部署开发环境:
在一个应用项目中(比如 GatewayService 中)开发本项目
在应用中(比如 GatewayService 中)进入 Pipenv 环境
先执行 pip3 uninstall fpfdb (需要清除掉已经安装的发布包,方便通过 link 引入一个远程链接)
不改变 virtualenv 的情况下,切换目录到本项目
执行 python3 setup.py develop (建立一个本项目的python库链接):
(venv) F:\projects\python-GatewayService>cd ..
(venv) F:\projects>
(venv) F:\projects>cd python-FPFDatabase
(venv) F:\projects\python-FPFDatabase>python setup.py develop
(venv) F:\projects\python-edgesdk>python setup.py develop
24.连mysql
root@unassigned-hostname:~# mysql -h 127.0.0.1 -P 3306 -uroot -p
Enter password:
root@unassigned-hostname:~# netstat -tanp # 查看端口占用情况
netstat -antp | grep ssh
Active Internet connections (servers and established)
root@unassigned-hostname:~# cd /iotdata/
root@unassigned-hostname:/iotdata# ll
total 28 # /iotdata空间比较大28M
ll:罗列出当前文件或目录的详细信息,含有时间、读写权限、大小、时间等信息
root@unassigned-hostname:/iotdata# df -h # 获取硬盘被占用了多少空间,目前还剩下多少空间等信息 -h 方便阅读方式显示
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# vim docker-compose.yaml
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# docker-compose up -d # 修改了yaml文件要重启镜像
Recreating mysql ...
25.数据库升级方式(迁移):
由于当前项目管理多个数据库,所有操作均需要用-n指定数据库(即alembic.ini配置的section名称)。
(python-FPFDatabase) F:\projects\python-FPFDatabase>alembic -n admin_system upgrade head
(python-FPFDatabase) F:\projects\python-FPFDatabase>alembic -n gateway upgrade head
--
(python-edgedatabasemigrations) F:\projects\python-edgedatabasemigrations>alembic upgrade head
26.跑启
连接到linux(自带docker)=>把simple包(python-GatewayServiceCluster)拷到linux=>用docker-compose方法启动,便安装了mysql、redis、mqtt=>安装MySQL客户端,创建相关数据库(无表)=>把相关项目拉下来,配虚拟环境,配.env文件=>在终端用alembic命令,迁移生成表,映射ORM到创建的数据库中
27.创建数据库
CREATE DATABASE IF NOT EXISTS gateway DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
28.TLS
传输层安全性协议(英语:Transport Layer Security,缩写作TLS),及其前身安全套接层(Secure Sockets Layer,缩写作SSL)是一种安全协议,目的是为互联网通信提供安全及数据完整性保障。网景公司(Netscape)在1994年推出首版网页浏览器,网景导航者时,推出HTTPS协议,以SSL进行加密,这是SSL的起源。
31.python 制作egg库以及打包
32.
print(os.path.abspath(".")) #当前目录的绝对路径
os.path.splitext(“文件路径”) 分离文件名与扩展名;默认返回(fname,fextension)元组,可做分片操作
file_path = Path(__file__)
print(file_path)
print(file_path.name)
res = os.path.splitext(file_path.name)
print(res)
base_file_name = os.path.join(os.path.abspath("./logs"), f"{res[0]}.log")
print(base_file_name)
# F:\projects\python - GatewayService\settings.py
# ('settings', '.py')
# F:\projects\python - GatewayService\logs\settings.log
33.
Gateway 网联注册队列
Topic id: topic/manager/gateway/upward
说明:公共队列,网联第一次接入 MQTT 之前,没有 gateway_id (网联 id),需往此队列发送网联注册消息。
upward:网联注册消息
消息流向:gatewayservice --> gateway
Topic:topic/{gateway_id}/app_to_gateway # app-代表FPF引擎
34.引擎与网联数据通讯协议
1. GatewayService 引擎与 Gateway 网联通讯模型
后台应用通过 MQTT 协议与网联进行通讯,QOS 设为: 1.
2. 网联和饲喂器的注册
网联接入系统之前,先通过 mac 地址往 MQTT 服务特定的消息队列发送注册消息,得到 gateway_id,用于唯一的网联身份鉴别,并且这个 gateway_id 也和该网联发送的消息队列的 topic 绑定;饲喂器的注册通过专门的配置工具来配置,饲喂器 id 由系统后台指定生成。饲喂器 id 由 3 位数字组成,从 000 至 999,地址通过拨线方式生成。
3. MQTT 消息队列定义
GatewayService 引擎和 GateWay 网联之间通过 MQTT 服务通讯,MQTT 服务上维护 4 条消息队列,其中 2 条为公共队列,另 2 条为引擎与特定网联的通讯队列;
3.1 Gateway 网联注册队列
Topic id: topic/manager/gateway/upward
说明:公共队列,网联第一次接入 MQTT 之前,没有 gateway_id (网联 id),需往此队列发送网联注册消息。
3.2 Gateway 网联注册响应队列
Topic id: topic/manager/gateway/downward
说明:公共队列,引擎收到网联注册消息后,往此队列发送网联注册响应消息,下发 gateway_id。
3.3 Gateway 网联响应指令、上报数据或主动请求消息队列
Topic id: topic/{gateway_id}/gateway_to_app
说明:网联响应指令、上报数据或主动请求消息队列,网联注册成功后,通过此队列与引擎交互,引擎订阅此队列监测来自网联的消息;
3.4 GatewayService 引擎下发指令队列
Topic id: topic/{gateway_id}/app_to_gateway
说明:引擎下发指令队列,引擎得到 gateway_id (网联 id)之后,通过此队列与网联交互,网联需订阅此队列监测来自引擎的指令;
4. 消息定义-全部以 JSON 形式
消息状态码 code 定义:
0 表示成功,非 0 表示失败;
消息类型 msg_type:偶数代表消息发送,奇数消息消息反馈;
35.gevent加锁
Semaphore是gevent提供的信号量,实例化为Semaphore(value), value代表了可以并发的量。当value为1,就变成了互斥锁(Lock)。Semaphore提供了两个函数,acquire(P操作)和release(V操作)import geventfrom gevent.lock import Semaphore
sem = Semaphore(1)
def f1():
for i in range(5):
sem.acquire()
print 'run f1, this is ', i
sem.release()
gevent.sleep(1)
36.redis
Redis Ping 命令使用客户端向 Redis 服务器发送一个 PING,如果连接正常就返回一个 PONG ,否则返回一个连接错误
连接redis,加上decode_responses=True,写入的键值对中的value为str类型,不加这个参数写入的则为字节类型。
redis_client.set('id',100,ex=60) # 60秒过期
37.
print("topic/{gateway_id}/gateway_to_app".replace("{gateway_id}", "\d{4}"))
x='topic/\d{4}/gateway_to_app'
import re
res=re.match(x,'topic/1234/gateway_to_app') # 匹配不到返回None
print(res)
# topic/\d{4}/gateway_to_app
# <_sre.SRE_Match object; span=(0, 25), match='topic/1234/gateway_to_app'>
38.abstractmethod装饰器
继承了含abstractmethod方法的子类必须复写所有abstractmethod装饰的方法,未被装饰的可以不重写
@abstractmethod
def on_message(self, client, userdata, msg):
self.logger.debug("message received, topic: {msg.topic}, payload: {msg.payload}".format(msg=msg))
41.mqtt服务器连不上
emqttd | sed: can't create temp file '/opt/emqttd/etc/emq.confXXXXXX': Permission denied
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# cat docker-compose.yaml
# - ./docker_datas/emqttd/etc:/opt/emqttd/etc # 注掉我们写的配置,启用mqtt自带的配置
simple-deployment\docker_datas\emqttd\etc
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment# chmod 755 -R docker_datas/
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment/docker_datas/emqttd/etc# cat emq.conf
42.通过telnet查某个端口是否打开
终端:telnet 172.20.6.196 1883
43.用xshell传文件
安装:lrzsz
lrzsz是一款在linux里可代替ftp上传和下载的程序,支持xshell和SecureCRT上传下载,其他没有试过,好像putty不支持!
root@unassigned-hostname:~/ouy/python-GatewayServiceCluster/simple-deployment/docker_datas# apt install lrzsz
root@unassigned-hostname:~# cd ouy
root@unassigned-hostname:~/ouy# rz # 选文件 传入
root@unassigned-hostname:~/ouy# ls
aa.zip python-GatewayServiceCluster
root@unassigned-hostname:~/ouy# sz aa.zip # 传出
root@unassigned-hostname:~/ouy#
44.
Python中UUID可以用int十进制,或hex十六进制显示,没有-分隔符用起来更方便。
>>> uuid.uuid1().int
73221012087113356936998119716747445800
>>> uuid.uuid1().hex
'6e574a3e051211e99b06d4619d2b8628'
45.ABCMeta
class Animal(metaclass=abc.ABCMeta): #只能被继承,不能实例化,实例化会报错:Can't instantiate abstract class
@abc.abstractmethod # 上述代码子类是约定俗称的实现这个方法,加上@abc.abstractmethod装饰器后严格控制子类必须实现这个方法
def talk(self):
raise AttributeError('子类必须实现这个方法')
45.
dict1 = dict.fromkeys(('Google', 'Runoob', 'Taobao'), None)
dict1.update((('ouy', 10), ('ouy2', 10)))
print(dict1)
# {'Google': None, 'Runoob': None, 'Taobao': None, 'ouy': 10, 'ouy2': 10}
46.
class Person(object):
def __init__(self, name, gender, **kw):
self.name = name
self.gender = gender
for k, v in kw.items():
# self.k = v # 报错
setattr(self, k, v)
p = Person('Bob', 'Male', age=18, course='Python')
print(p.age)
print(p.__dict__)
# 18
# {'name': 'Bob', 'gender': 'Male', 'age': 18, 'course': 'Python'}
47.
a={'name': 'Bob', 'gender': 'Male', 'age': 18, 'course': 'Python'}
b=a.pop('name',10) # Bob
print(b)
print(a)
# Bob
# {'gender': 'Male', 'age': 18, 'course': 'Python'}
48.
import schedule
import time
def job():
print("I'm working...")
schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at("10:30").do(job)
schedule.every(5).to(10).days.do(job)
schedule.every().monday.do(job)
schedule.every().wednesday.at("13:15").do(job)
while True:
schedule.run_pending()
time.sleep(1)
49.
from enum import Enum, unique
@unique # 重复会报错=>找重复值
class Weekday(Enum): # 当Class中有重复值时,会返回第一个,其他忽略
monday = 3
tusday = 1
wensdday =4
thursday =9
friday =5
for n, y in Weekday.__members__.items():
print(n, '--', y, '--', y.value)
f = Weekday.thursday
print(f.value)
3.25=======================
50.
if callable(callback):
Return whether the object is callable
51.
非阻塞调用协程
to run func(*args, **kwargs)[in *seconds* later]:
gevent.spawn_later(3,func,*args,**kwargs)
gevent.spawn(func,*args,**kwargs)
gevent.sleep(10)
53.
msg_uuids=[1,2,3,4,'0']
msg_uuids.remove("0") if "0" in msg_uuids else None # 移除占位的 msg_uuid
print(msg_uuids)
54.
Apidoc
终端:
安装node.js
安装apiDoc
npm install apidoc -g
apidoc.json:
{
"name": "API Doc for FPF Engine Admin Service",
"title": "Engine Admin Service 接口文档",
"version": "2.0.0",
"url": "http://{engine_host}/fpf/api/v1",
"sampleUrl": "http://172.20.6.10/fpf/api/v1",
"header": {
"title": "Readme",
"filename": "Learning tracker"
},
"footer": {
"title": "错误代码说明",
"filename": "error_code.md"
},
"template": {
"withGenerator": true,
"withCompare": true
},
"order": [
"Config",
"Command",
"DeviceInfo",
"Feeding",
"Upgrade"
]
}
说明:
| url | api访问根地址 |
| order | 排序,先get后post |
| template | 生成模版,withCompare,支持版本比较,withGenerator 是否显示apidoc官方支持,false不显示 |
| header | 头部模版 |
| footer | 尾部模版 |
55.
.sh文件
linux中.sh文件一般都是bash脚本,包含一些可执行的命令
执行:
ouyangling@ŷ▒▒▒▒ MINGW64 ~/Desktop/apidocs (develop)
$ sh auto_generate.sh
56.RFID读卡器
RFID读卡器是一种能阅读电子标签数据的自动识别设备。根据阅读标签频率的不同分为低频、高频、超高频读卡器。RFID读卡器需配备RFID天线一起使用才能读取标签信息。
57.
multiprocessing.freeze_support() # 在Windows下编译需要加这行
大致就是windows创建进程没有fork方法,默认是spawn,而linux创建进程默认是fork方法。
58.
zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0
a='ouy_in_sz'
print(a.zfill(20))
# 00000000000ouy_in_sz
59.rancher?
60.更新fpfdb
A.
在一个应用项目中(比如 GatewayService 中)开发本项目
在应用中(比如 GatewayService 中)进入 Pipenv 环境
先执行 pip3 uninstall fpfdb (需要清除掉已经安装的发布包,方便通过 link 引入一个远程链接)
不改变 virtualenv 的情况下,切换目录到本项目
执行 python3 setup.py develop (建立一个本项目的python库链接)
B.
pip install --user devpi
devpi use https://devpi.idereck.com/root/idereck
devpi login root --password=Shadow.devpi
devpi upload
这个一般是发布用的,谨慎操作,因为会影响到使用方
61.
getattr(self, 'edge_client').pub_device_rpc_request(
payload=json.dumps(payload)) # Transfer business message to cloud success
# getattr(self, 'edge_client').pub(payload=json.dumps(payload)) # Transfer message format invalid
62.发版数据库新版本
Setup.puy
name="fpfdb", version="1.3.0",
切到/f/projects_02/python-FPFDatabase:执行以下命令
pip install --user devpi
devpi use https://devpi.sz.yingzi.com/root/idereck
devpi login root --password=Shadow.devpi
devpi upload
63.重命名git分支
git push --delete origin feature/optimizing
git branch -m feature/optimizing release/2.2.1
git push origin release/2.2.1
64.edge-core:
vim docker_datas/configs/envs/edge/edge-core-service.env
====》
# edge core service
DEBUG=True
# Redis
REDIS_SERVER_HOST=redis
REDIS_SERVER_PORT=6379
REDIS_SERVER_PASSWORD=
# Basic Service
MQTT_SERVER_HOST=emqx
MQTT_SERVER_PORT=11883
# ECCP
# 德里克边缘计算控制平台接入配置
ECCP_MQTT_SERVER_HOST=thingsboard.idereck.com
ECCP_MQTT_SERVER_PORT=3883
# 以下变量ansible会根据每台引擎的配置单独设置
ECCP_ACCESS_ENABLED=False
ECCP_ACCESS_TOKEN=
ECCP_MQTT_CLIENT_ID=
# Yingzi Cloud
# IOT_MQTT_SERVER_HOST=tb-mqtt-transport.test.yingzi.com
# IOT_MQTT_SERVER_PORT=30538
IOT_MQTT_SERVER_HOST=tb-mqtt-transport.dev.yingzi.com
IOT_MQTT_SERVER_PORT=40438
# 以下变量ansible会根据每台引擎的配置单独设置
IOT_ACCESS_ENABLED=True
IOT_MQTT_CLIENT_ID=78049000-6e52-11ea-9db9-fd327120c6c5
IOT_ACCESS_TOKEN=DluYUJVjNSKYREINyW6R
# ouy 6.11
BASE_URL = "http://yingzi-iot-hub.dev.yingzi.com"
DEVICE_CODE = "78049000-6e52-11ea-9db9-fd327120c6c5"
ACCESS_TOKEN = "DluYUJVjNSKYREINyW6R"