在 Jenkins 上部署 Python 项目
使用流水线部署 Python 项目
使用流水线部署 Python 项目
Spring Boot 项目打包之后一般都比较大,远程部署过程速度慢,而且浪费很多的资源
通过轻量化部署,将项目依赖分开打包,实际代码 jar 就会变得很小,可以快速部署到服务器上
maven-assembly-plugin 是一个 Maven 插件,用于将项目及其依赖打包成一个可分发的归档文件(如 ZIP、TAR、JAR 等)。它通常用于创建包含所有依赖、配置文件和资源的完整发布包
<plugin> |
在src/assembly/assembly.xml中定义打包的规则
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" |
如果项目是多模块项目,那么对于项目自身模块的jar包, 直接到 include打到打包后的jar中
<plugin> |
示例项目为拥有2个模块的maven项目,base模块为基础模块,business模块为业务模块,启动业务模块引用了基础模块
打包时候需要将base模块打包到jar中
项目目录如下
demo模块的pom如下
<?xml version="1.0" encoding="UTF-8"?> |
base模块的pom如下
<?xml version="1.0" encoding="UTF-8"?> |
business模块的pom文件如下
<?xml version="1.0" encoding="UTF-8"?> |
mvn clean package |
business模块打包后如下
business-0.0.1-SNAPSHOT.zip 压缩包里面包含了项目的依赖
构建之后的business-0.0.1-SNAPSHOT.jar也包含了base模块
spring-boot-jarmode-tools使用springboot优化分层结构的hjar包(在一些版本可能没有)
需要执行项目依赖库
-Dloader.path=lib |
启动命令如下
java "-Dloader.path=lib" -jar business-0.0.1-SNAPSHOT.jar |
启动成功
可以将项目的依赖库目录lib挂载到docker容器目录,
# 使用官方 OpenJDK 17 作为基础镜像 |
docker容器的启动如下
docker run -p 8080:8080 -v /data/lib:/app/lib my-spring-boot-app |
-v /data/lib:/app/lib 将系统目录/data/lib映射到容器的/app/lib
只需要将依赖的jar解压到/data/lib即可
在开始学习 BACnet之前,我们先下载一个BACnet模拟器 Yabe (Yet Another BACnet Explorer)
下载地址可以点击此处 ,文章版本是 1.3.2
下载并安装
可以在导航栏看到
其中 BACnet.Room.Simulator 是BACnet设备仿真,可以让模拟现实中一个室内控制设备
打开软件,可以看到是一个温度控制传感器
左下角是预定的三种模式,分别是Comfort(舒适)、Eco+(环境友好)、Vacancv(空缺)
其实就是对应着不同的温度,例如图中选了1 Comfort,对应的温度是21°,此时室外温度是12° (分别是上面2个温度)
其中20.7°C则表示当前室内温度
底下是BACnet的设备Id:458942
简单了解之后,我们使用Yabe来扫描这个设备
右键点击Devices,然后选中 Add device
查看BACnet的一些链接参数
我们通过BACnet/IP V4方式连接
端口号使用即可,再选择一下IP地址(172.29.224.1 这是我本地的ip)
点击start,Yabe会在这个网段广播,扫描BACnet 设备
我们可以启动多个仿真,对应不同房间的设备
每个BACnet设备都有一个设备id
可以看到两台设备的设备id分别是 458942,458943
每个BACnet设备有一些寄存器地址(Address Space),用于存储不同的点位
BACnet的设备字段根据类型可以分为
AI、AO、AV、BI、BO、BV、MI、MO、MV
| 类型 | 读 | 写 | 描述 |
|---|---|---|---|
| AI | 可读 | 不可 | Analog Input |
| AO | 可读 | 可写 | Analog Output |
| AV | 可读 | 可写 | Analog Value |
| BI | 可读 | 不可 | Binary Input |
| BO | 可读 | 可写 | Binary Output |
| BV | 可读 | 可写 | Binary Value |
| MI | 可读 | 不可 | Multi State Input |
| MO | 可读 | 可写 | Multi State Output |
| MV | 可读 | 可写 | Multi State Value |
除了 Input 为只读之外,其他都是可读可写
在 RoomControl 这个设备里,AI0 AI1 AI2 分别表示室内温度、热水温度、室外温度
室内温度
水温
室外温度
可以看到AI类型有以上这些字段
| 字段 | 描述 |
|---|---|
| Description | BACnet对象的字段description,用于进一步描述对象 |
| Event State | 事件状态 |
| Object Identifier | BACnet对象ID,格式为object-type,object-instance-number |
| Object Name | BACnet对象的名称,用于描述对象的字段namedescription |
| Object Type | 对象的BACnet类型,例如analog-input |
| Out Of Service | 不可使用 |
| Present Value | 当前值属性 |
| Reliability | 可靠性 |
| Status Flags | 状态位 |
| Units | 单位 |
AV1 AV2 AV3 分别对应仿真的三个温度模式(Comfort/Eco+/Vacancv)的温度值
可以通过修改Present Value来改变仿真终端的数值
例如修改 SetPoint 1的值为31.1 ,可以看到终端上的温度也变成31.1
我们还可以将BACnet Object 拖拽到监听点位,在下方就可以数值变化的曲线,方便我们观察指标的变化
我们本地使用迅绕的自控网关
在网关配置了BACnet IP 转发
点位如下
我们使用Java代码来读写点位
首先引入依赖
<dependency> |
编写一个简单测试方式来测试
这个例子使用IP直连的方式,而不是上面使用Yabe时用的广播方式
public class BACnetClientTest { |
上面的程序主要是通过BACnet与远程设备通行,并读取对象的属性值
代码解释
IpNetwork network = new IpNetworkBuilder() |
BACnetClient client = new BACnetXClient(localDevice); |
这里BACnetXClient 是自己重新封装的,因为类库提供的没有提供LocalDevice,所以重新封装一个,源码在附录1
int deviceId = 2605; |
这里提供远程设备的ip、端口和设备id
创建一个Device对象工厂,使用远程设备创建一个Device,用于读写操作
DefaultDeviceFactory defaultDeviceFactory = new DefaultDeviceFactory(); |
BACnetObject BACnetObject = new BACnetObject(device, 0, BACnetObjectTypeEnum.ANALOG_INPUT.getType()); // 创建一个BACnet的数据类型 |
本地使用BACnetObjectTypeEnum封装BACnet的数据类型
BACnetObject BACnetObject = new BACnetObject(device, 0, BACnetObjectTypeEnum.ANALOG_OUTPUT.getType()); // 创建 AO 0 点 |
设置之后
可以看到点位值变成3
说明点位写入成功
代码原理如下图
在启动客户端 client.start() 之后,底层还先后执行transport和network两个实体的初始化方法 initialize ,并启动各自的内置线程
LocalDevice 的 initialize 方法
public synchronized LocalDevice initialize(RestartReason lastRestartReason) throws Exception { |
Transport 的 initialize 方法
public void initialize() throws Exception { |
在 Transport 的 run 方法内处理 数据报文的出入 (Transport 实现 Runnable 接口 )
public void run() { |
Network 的 initialize 方法
public void initialize(Transport transport) throws Exception { |
在 Network 里面接收并处理数据报文
public void run() { |
通过本文学习,可以简单了解 BACnet 进行设备仿真、扫码设备、读写设备属性等基本操。通过 Java 代码进行于 BACnet设备进行交互,以及简单了解bacnet4j 基础类库的基本原理
BacNetXClient 实体类
import com.serotonin.bacnet4j.LocalDevice; |
参考 org.code_house.bacnet4j.wrapper.ip.BacNetIpClient 开发的一个客户端,增加一个 BacNetXClient(LocalDevice localDevice) 的构造参数
tdengine2.4升到 tdengine3.0
需要将taos的驱动包升级到3以上
<dependency> |
然后处理代码
公司使用 mybatis 作为 tdengine 的 ORM 框架,所以 sql 编写在 XML 文件中
需要调整一下 sql 来兼容tdengine3
在字段上,我们使用到了 tdengine 的一些关键字,例如 value, index 等
需要在关键字前后添加反引号(`)
修改前
select last(value) from t_xxx; |
修改后
select last(`value`) from t_xxx; |
时间窗口函数interval在时序数据库的场景中用得比较频繁,
升级到 tdengine3 之后,无法与 group by 关键字一起使用,
需要替换成partition bypartition by在使用上与group by一样
partition语句放在where语句之后,interval语句之前
修改前
SELECT last(value), c_time, sensor_id |
修改后
SELECT last(`value`), c_time, sensor_id |
使用 taos 自动的导入导出工具,可以很方便实现数据的迁移,下载链接
在2.x版本,建议安装taosTools官方安装包,避免导出格式无法兼容3.x版本而出现一些错误
通过以下命令
taosdump -o export -D iot_db -T 8 |
-o 指定导出目录,需要先建立,不指定导出到当前目录,如果导出目录不为空,则会报错-D指定导出的数据库,可以使用-A导出所有数据库-T 指定线程大小,默认是8个线程
taosdump -i export |
-i 指定导入目录