Release:5.20灰测
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
local log = require "log"
|
local log = require "log"
|
||||||
local sys = require "sys"
|
local sys = require "sys"
|
||||||
local uart = require "uart"
|
local uart = require "uart"
|
||||||
|
local ril = require "ril"
|
||||||
local linksocket = require "linksocket"
|
local linksocket = require "linksocket"
|
||||||
|
|
||||||
local uartID = 1
|
local uartID = 1
|
||||||
@@ -18,14 +19,27 @@ local function toHexcode(str)
|
|||||||
return hex
|
return hex
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 发送通用响应帧:55 AA mainCmd subCmd [payload] AA 55
|
||||||
|
local function sendCmdResponse(mainCmd, subCmd, payload)
|
||||||
|
local frame = string.char(0x55, 0xAA, mainCmd, subCmd)
|
||||||
|
if payload and #payload > 0 then
|
||||||
|
frame = frame .. payload
|
||||||
|
end
|
||||||
|
frame = frame .. string.char(0xAA, 0x55)
|
||||||
|
uart.write(uartID, frame)
|
||||||
|
log.debug("sendCmdResponse: mainCmd=", string.format("0x%02X", mainCmd),
|
||||||
|
"subCmd=", string.format("0x%02X", subCmd))
|
||||||
|
end
|
||||||
|
|
||||||
-- 发送通用响应帧:55 AA 83 subCmd socketId status AA 55
|
-- 发送通用响应帧:55 AA 83 subCmd socketId status AA 55
|
||||||
local function sendResponse(subCmd, socketId, status)
|
local function sendResponse(subCmd, socketId, status)
|
||||||
local frame = string.char(0x55, 0xAA, 0x83, subCmd, socketId, status, 0xAA, 0x55)
|
sendCmdResponse(0x83, subCmd, string.char(socketId, status or 0))
|
||||||
uart.write(uartID, frame)
|
|
||||||
log.debug("Response: subCmd=", subCmd, "socketId=", socketId, "status=", status)
|
log.debug("Response: subCmd=", subCmd, "socketId=", socketId, "status=", status)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 命令处理函数
|
-- 命令处理函数 ---------------------------------------------------------------
|
||||||
|
|
||||||
|
-- 0x01: 数据发送到指定Socket
|
||||||
local function handleCmd01(subCmd, payload)
|
local function handleCmd01(subCmd, payload)
|
||||||
local socketId = subCmd
|
local socketId = subCmd
|
||||||
if socketId < 1 or socketId > 6 then
|
if socketId < 1 or socketId > 6 then
|
||||||
@@ -42,57 +56,155 @@ local function handleCmd01(subCmd, payload)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 0x02: 系统重启
|
||||||
local function handleCmd02()
|
local function handleCmd02()
|
||||||
log.info("System restart command received")
|
log.info("System restart command received")
|
||||||
sys.restart()
|
sys.restart()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 0x03: Socket连接/断开控制
|
||||||
|
-- subCmd: 0x01=连接 0x02=断开
|
||||||
|
-- payload: socket_id (1字节)
|
||||||
local function handleCmd03(subCmd, payload)
|
local function handleCmd03(subCmd, payload)
|
||||||
if #payload < 1 then
|
if #payload < 1 then return end
|
||||||
log.error("Cmd 0x03 missing socket id")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local socketId = payload:byte(1)
|
local socketId = payload:byte(1)
|
||||||
if socketId < 1 or socketId > 6 then
|
if socketId < 1 or socketId > 6 then
|
||||||
log.error("Invalid socket id in cmd 0x03:", socketId)
|
log.error("Cmd 0x03 invalid socket:", socketId)
|
||||||
sendResponse(subCmd, socketId, 1)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if subCmd == 0x01 then
|
if subCmd == 0x01 then
|
||||||
local ok = linksocket.setKeepConnecting(socketId, true)
|
log.info("STM32 request connect socket", socketId)
|
||||||
if ok then
|
linksocket.connectSocket(socketId)
|
||||||
sendResponse(subCmd, socketId, 3)
|
|
||||||
else
|
|
||||||
sendResponse(subCmd, socketId, 1)
|
|
||||||
end
|
|
||||||
elseif subCmd == 0x02 then
|
elseif subCmd == 0x02 then
|
||||||
local ok = linksocket.setKeepConnecting(socketId, false)
|
log.info("STM32 request disconnect socket", socketId)
|
||||||
if ok then
|
linksocket.disconnectSocket(socketId)
|
||||||
sendResponse(subCmd, socketId, 0)
|
|
||||||
else
|
|
||||||
sendResponse(subCmd, socketId, 1)
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
log.error("Unknown subCmd for 0x03:", subCmd)
|
log.error("Unknown subCmd for 0x03:", subCmd)
|
||||||
sendResponse(subCmd, socketId, 1)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 对外接口:处理串口接收到的原始数据
|
-- 0x04: 设置服务器地址
|
||||||
local function process(rawData)
|
-- payload: ip_len(1) + ip_str(ip_len) + port_hi(1) + port_lo(1)
|
||||||
if not rawData or #rawData < 5 then
|
local function handleCmd04(subCmd, payload)
|
||||||
log.warn("Short data received, ignore")
|
if #payload < 3 then
|
||||||
|
log.error("Cmd 0x04 payload too short")
|
||||||
|
sendCmdResponse(0x87, 0x00, string.char(1))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local ip_len = payload:byte(1)
|
||||||
|
if ip_len > 100 or #payload < (2 + ip_len + 1) then
|
||||||
|
log.error("Cmd 0x04 invalid ip_len")
|
||||||
|
sendCmdResponse(0x87, 0x00, string.char(1))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local ip_str = payload:sub(2, 1 + ip_len)
|
||||||
|
local port_hi = payload:byte(2 + ip_len)
|
||||||
|
local port_lo = payload:byte(3 + ip_len)
|
||||||
|
local port = port_hi * 256 + port_lo
|
||||||
|
|
||||||
|
log.info("Set server address:", ip_str, port)
|
||||||
|
|
||||||
|
local ok = linksocket.setServerAddress(ip_str, port)
|
||||||
|
if ok then
|
||||||
|
sendCmdResponse(0x87, 0x00, string.char(0))
|
||||||
|
else
|
||||||
|
sendCmdResponse(0x87, 0x00, string.char(1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 0x05: 查询SIM卡信息
|
||||||
|
-- subCmd: 0x01=ICCID 0x02=IMSI 0x03=IMEI
|
||||||
|
local function handleCmd05(subCmd)
|
||||||
|
local at_cmds = {
|
||||||
|
[0x01] = "AT+ICCID",
|
||||||
|
[0x02] = "AT+CIMI",
|
||||||
|
[0x03] = "AT+CGSN",
|
||||||
|
}
|
||||||
|
local at_cmd = at_cmds[subCmd]
|
||||||
|
if not at_cmd then
|
||||||
|
log.error("Unknown SIM query type:", string.format("0x%02X", subCmd))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
log.info("CMD raw data:", toHexcode(rawData))
|
ril.request(at_cmd, nil, function(cmd, result, respdata, interdata)
|
||||||
|
-- interdata才是实际的AT命令响应数据,result只是布尔值表示成功/失败
|
||||||
|
local response = interdata or ""
|
||||||
|
-- 去除可能的空白字符
|
||||||
|
response = response:gsub("^[\r\n]+", ""):gsub("[\r\n]+$", "")
|
||||||
|
|
||||||
if rawData:byte(1) == 0x55 and rawData:byte(2) == 0xAA
|
local value = ""
|
||||||
and rawData:byte(-2) == 0xAA and rawData:byte(-1) == 0x55 then
|
if subCmd == 0x01 then
|
||||||
local mainCmd = rawData:byte(3)
|
value = string.match(response, "%+ICCID:%s*(%S+)") or string.match(response, "ICCID:%s*(%S+)") or response:match("^(%S+)") or ""
|
||||||
local subCmd = rawData:byte(4)
|
elseif subCmd == 0x02 then
|
||||||
local payload = rawData:sub(5, -3)
|
value = string.match(response, "%+CIMI:%s*(%S+)") or string.match(response, "CIMI:%s*(%S+)") or response:match("^(%S+)") or ""
|
||||||
|
elseif subCmd == 0x03 then
|
||||||
|
value = string.match(response, "%+CGSN:%s*(%S+)") or string.match(response, "CGSN:%s*(%S+)") or response:match("^(%S+)") or ""
|
||||||
|
end
|
||||||
|
|
||||||
|
value = value or ""
|
||||||
|
log.info("SIM query result type=", string.format("0x%02X", subCmd), "value=", value)
|
||||||
|
|
||||||
|
local data = string.char(#value) .. value
|
||||||
|
sendCmdResponse(0x84, subCmd, data)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 0x06: 查询信号强度(CSQ)
|
||||||
|
local function handleCmd06()
|
||||||
|
ril.request("AT+CSQ", nil, function(cmd, result)
|
||||||
|
local csq = 0
|
||||||
|
local ber = 99
|
||||||
|
-- result可能是布尔值,需要确保是字符串才能进行模式匹配
|
||||||
|
if result and type(result) == "string" then
|
||||||
|
local c, b = string.match(result, "CSQ:%s*(%d+),%s*(%d+)")
|
||||||
|
if c then csq = tonumber(c) or 0 end
|
||||||
|
if b then ber = tonumber(b) or 99 end
|
||||||
|
end
|
||||||
|
log.info("Signal query: CSQ=", csq, "BER=", ber)
|
||||||
|
sendCmdResponse(0x85, 0x01, string.char(csq, ber))
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 0x07: 查询链路状态
|
||||||
|
local function handleCmd07()
|
||||||
|
local status = linksocket.getLinkStatus()
|
||||||
|
if status then
|
||||||
|
local payload = ""
|
||||||
|
for i = 1, 6 do
|
||||||
|
payload = payload .. string.char(status[i] and 1 or 0)
|
||||||
|
end
|
||||||
|
sendCmdResponse(0x86, 0x01, payload)
|
||||||
|
log.info("Link status sent, 6 sockets")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local frameBuffer = ""
|
||||||
|
|
||||||
|
-- 对外接口:处理串口接收到的原始数据
|
||||||
|
local function process(rawData)
|
||||||
|
if not rawData or #rawData < 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
frameBuffer = frameBuffer .. rawData
|
||||||
|
|
||||||
|
while true do
|
||||||
|
if #frameBuffer < 7 then break end
|
||||||
|
|
||||||
|
if frameBuffer:byte(1) == 0x55 and frameBuffer:byte(2) == 0xAA then
|
||||||
|
local tail = frameBuffer:find(string.char(0xAA, 0x55), 5, true)
|
||||||
|
if not tail then break end
|
||||||
|
tail = tail + 1
|
||||||
|
|
||||||
|
local frame = frameBuffer:sub(1, tail)
|
||||||
|
frameBuffer = frameBuffer:sub(tail + 1)
|
||||||
|
|
||||||
|
log.info("CMD raw data:", toHexcode(frame))
|
||||||
|
|
||||||
|
local mainCmd = frame:byte(3)
|
||||||
|
local subCmd = frame:byte(4)
|
||||||
|
local payload = frame:sub(5, -3)
|
||||||
|
|
||||||
if mainCmd == 0x01 then
|
if mainCmd == 0x01 then
|
||||||
handleCmd01(subCmd, payload)
|
handleCmd01(subCmd, payload)
|
||||||
@@ -100,11 +212,27 @@ local function process(rawData)
|
|||||||
handleCmd02()
|
handleCmd02()
|
||||||
elseif mainCmd == 0x03 then
|
elseif mainCmd == 0x03 then
|
||||||
handleCmd03(subCmd, payload)
|
handleCmd03(subCmd, payload)
|
||||||
|
elseif mainCmd == 0x04 then
|
||||||
|
handleCmd04(subCmd, payload)
|
||||||
|
elseif mainCmd == 0x05 then
|
||||||
|
handleCmd05(subCmd)
|
||||||
|
elseif mainCmd == 0x06 then
|
||||||
|
handleCmd06()
|
||||||
|
elseif mainCmd == 0x07 then
|
||||||
|
handleCmd07()
|
||||||
else
|
else
|
||||||
log.warn("Unknown main command:", mainCmd)
|
log.warn("Unknown main command:", string.format("0x%02X", mainCmd))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.warn("Invalid frame header/footer")
|
local skip = frameBuffer:find(string.char(0x55, 0xAA), 2, true)
|
||||||
|
if skip then
|
||||||
|
log.warn("Skipped", skip - 1, "bytes before frame header")
|
||||||
|
frameBuffer = frameBuffer:sub(skip)
|
||||||
|
else
|
||||||
|
frameBuffer = ""
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,159 +1,263 @@
|
|||||||
-- linksocket.lua
|
-- linksocket.lua
|
||||||
-- 功能:管理多个 TCP Socket 连接,支持手动连接/断开,自动重连,数据收发
|
-- 功能:管理多个 TCP Socket
|
||||||
|
-- 行为:接收到连接命令后尝试连接一次
|
||||||
|
-- 连接失败 → 主动上报失败 (0x83 03)
|
||||||
|
-- 连接成功 → 主动上报成功 (0x83 01)
|
||||||
|
-- 中途掉线 → 主动上报断开 (0x83 02),停止,等待新连接命令
|
||||||
|
|
||||||
local log = require "log"
|
local log = require "log"
|
||||||
local sys = require "sys"
|
local sys = require "sys"
|
||||||
local socket = require "socket"
|
local socket = require "socket"
|
||||||
-- 服务器配置
|
local sim = require "sim"
|
||||||
local SERVER_IP = "129.211.170.245"
|
|
||||||
local SERVER_PORT = 9002
|
-- 云快充
|
||||||
|
-- local server_config = {
|
||||||
|
-- ip = "121.43.69.62",
|
||||||
|
-- port = 8767
|
||||||
|
-- }
|
||||||
|
-- 百瑞
|
||||||
|
|
||||||
|
local server_config = {
|
||||||
|
ip = "129.211.170.245",
|
||||||
|
port = 9002
|
||||||
|
}
|
||||||
|
-- 国网
|
||||||
|
-- local server_config = {
|
||||||
|
-- ip = "121.199.29.175",
|
||||||
|
-- port = 1883
|
||||||
|
-- }
|
||||||
|
|
||||||
|
|
||||||
local MAX_CLIENTS = 6
|
local MAX_CLIENTS = 6
|
||||||
|
|
||||||
-- 客户端状态表
|
|
||||||
local clients = {}
|
local clients = {}
|
||||||
local keepConnecting = {}
|
local connectRequested = {} -- 收到连接命令的标志
|
||||||
|
local disconnectRequested = {} -- 收到断开命令的标志
|
||||||
local recvCallback = nil
|
local recvCallback = nil
|
||||||
|
|
||||||
-- 初始化所有socket槽位
|
|
||||||
for i = 1, MAX_CLIENTS do
|
for i = 1, MAX_CLIENTS do
|
||||||
clients[i] = {
|
clients[i] = { id = i, socket = nil, connected = false }
|
||||||
id = i,
|
connectRequested[i] = false
|
||||||
socket = nil,
|
disconnectRequested[i] = false
|
||||||
connected = false
|
|
||||||
}
|
|
||||||
keepConnecting[i] = false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 发送连接状态响应
|
local uart
|
||||||
local function sendConnStatus(subCmd, socketId, status)
|
local function getUart()
|
||||||
local uart = require "uart"
|
if not uart then uart = require "uart" end
|
||||||
local frame = string.char(0x55, 0xAA, 0x83, subCmd, socketId, status, 0xAA, 0x55)
|
return uart
|
||||||
uart.write(1, frame)
|
|
||||||
log.debug("Socket", socketId, "status response, subCmd=", subCmd, "status=", status)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 设置是否保持连接
|
-- 发送状态通知到 STM32
|
||||||
local function setKeepConnecting(id, keep)
|
-- subCmd: 0x01=已连接 0x02=已断开 0x03=连接失败
|
||||||
if id < 1 or id > MAX_CLIENTS then
|
local function sendStatus(subCmd, socketId, status)
|
||||||
return false
|
local frame = string.char(0x55, 0xAA, 0x83, subCmd, socketId, status or 0, 0xAA, 0x55)
|
||||||
|
getUart().write(1, frame)
|
||||||
|
log.info("Socket", socketId,
|
||||||
|
subCmd == 0x01 and "connected" or
|
||||||
|
subCmd == 0x02 and "disconnected" or "connect_failed",
|
||||||
|
"status=", status or 0)
|
||||||
end
|
end
|
||||||
keepConnecting[id] = keep
|
|
||||||
if not keep and clients[id].connected and clients[id].socket then
|
-- 关闭单个socket
|
||||||
|
local function closeSocket(id)
|
||||||
|
if clients[id].socket then
|
||||||
clients[id].socket:close()
|
clients[id].socket:close()
|
||||||
clients[id].socket = nil
|
clients[id].socket = nil
|
||||||
|
end
|
||||||
clients[id].connected = false
|
clients[id].connected = false
|
||||||
sendConnStatus(0x02, id, 0)
|
connectRequested[id] = false
|
||||||
|
disconnectRequested[id] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ── 外部接口 ──────────────────────────────────────────
|
||||||
|
|
||||||
|
-- STM32 要求连接
|
||||||
|
local function connectSocket(id)
|
||||||
|
if id < 1 or id > MAX_CLIENTS then
|
||||||
|
log.error("connectSocket: invalid id", id)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if clients[id].connected then
|
||||||
|
log.info("Socket", id, "already connected")
|
||||||
|
sendStatus(0x01, id, 0)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
connectRequested[id] = true
|
||||||
|
disconnectRequested[id] = false
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- STM32 要求断开
|
||||||
|
local function disconnectSocket(id)
|
||||||
|
if id < 1 or id > MAX_CLIENTS then
|
||||||
|
log.error("disconnectSocket: invalid id", id)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
connectRequested[id] = false
|
||||||
|
disconnectRequested[id] = true
|
||||||
|
if clients[id].connected then
|
||||||
|
closeSocket(id)
|
||||||
|
sendStatus(0x02, id, 0)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 发送数据到指定socket
|
-- 发送数据
|
||||||
local function sendToSocket(id, data)
|
local function sendToSocket(id, data)
|
||||||
if id < 1 or id > MAX_CLIENTS then
|
if id < 1 or id > MAX_CLIENTS then return false end
|
||||||
log.error("sendToSocket: invalid id", id)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
if clients[id].connected and clients[id].socket then
|
if clients[id].connected and clients[id].socket then
|
||||||
clients[id].socket:asyncSend(data)
|
clients[id].socket:asyncSend(data)
|
||||||
log.info("Send to socket", id, "len=", #data)
|
|
||||||
return true
|
return true
|
||||||
else
|
end
|
||||||
log.warn("Socket", id, "not connected, cannot send")
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
-- 注册数据接收回调
|
|
||||||
local function setRecvCallback(cb)
|
local function setRecvCallback(cb)
|
||||||
recvCallback = cb
|
recvCallback = cb
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 为每个socket创建常驻任务
|
local function setServerAddress(ip, port)
|
||||||
|
if not ip or #ip == 0 or not port or port <= 0 or port > 65535 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
log.info("setServerAddress:", ip, port)
|
||||||
|
server_config.ip = ip
|
||||||
|
server_config.port = port
|
||||||
|
for id = 1, MAX_CLIENTS do
|
||||||
|
if clients[id].connected then
|
||||||
|
closeSocket(id)
|
||||||
|
sendStatus(0x02, id, 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getLinkStatus()
|
||||||
|
local status = {}
|
||||||
|
for i = 1, MAX_CLIENTS do
|
||||||
|
status[i] = clients[i].connected
|
||||||
|
end
|
||||||
|
return status
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ── 每个Socket的控制任务 ─────────────────────────────
|
||||||
for id = 1, MAX_CLIENTS do
|
for id = 1, MAX_CLIENTS do
|
||||||
sys.taskInit(function()
|
sys.taskInit(function()
|
||||||
local socketId = id
|
local socketId = id
|
||||||
log.debug("Socket", socketId, "control task started")
|
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
while not keepConnecting[socketId] do
|
-- 等待连接命令
|
||||||
|
while not connectRequested[socketId] do
|
||||||
|
sys.wait(500)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 用 do..break 代替 goto,确保失败/断开都回到外层循环顶部
|
||||||
|
repeat
|
||||||
|
disconnectRequested[socketId] = false
|
||||||
|
|
||||||
|
-- 等待网络就绪且SIM卡正常
|
||||||
|
while not socket.isReady() or not sim.getStatus() do
|
||||||
|
if disconnectRequested[socketId] then break end
|
||||||
|
local simStatus = sim.getStatus()
|
||||||
|
if not simStatus then
|
||||||
|
log.warn("Socket", socketId, "waiting for SIM card, status:", simStatus)
|
||||||
|
end
|
||||||
sys.wait(1000)
|
sys.wait(1000)
|
||||||
end
|
end
|
||||||
|
if disconnectRequested[socketId] then
|
||||||
while keepConnecting[socketId] do
|
connectRequested[socketId] = false
|
||||||
while not socket.isReady() do
|
break
|
||||||
if not keepConnecting[socketId] then break end
|
|
||||||
sys.wait(1000)
|
|
||||||
end
|
end
|
||||||
if not keepConnecting[socketId] then break end
|
-- 再次检查SIM卡状态,防止等待期间SIM卡被拔出
|
||||||
|
if not sim.getStatus() then
|
||||||
local sock = socket.tcp()
|
connectRequested[socketId] = false
|
||||||
log.debug("Socket", socketId, "connecting to", SERVER_IP, SERVER_PORT)
|
sendStatus(0x03, socketId, 2)
|
||||||
local connected = false
|
log.warn("Socket", socketId, "connect failed: SIM card not ready")
|
||||||
while not connected and keepConnecting[socketId] do
|
|
||||||
connected = sock:connect(SERVER_IP, SERVER_PORT)
|
|
||||||
if not connected then
|
|
||||||
log.warn("Socket", socketId, "connect failed, retry in 3s")
|
|
||||||
sys.wait(3000)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not keepConnecting[socketId] then
|
|
||||||
if sock then sock:close() end
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 尝试连接(只试一次)
|
||||||
|
local sock = socket.tcp()
|
||||||
|
log.info("Socket", socketId, "connecting to",
|
||||||
|
server_config.ip, server_config.port)
|
||||||
|
|
||||||
|
local ok = sock:connect(server_config.ip, server_config.port)
|
||||||
|
if disconnectRequested[socketId] or not ok then
|
||||||
|
if sock then sock:close() end
|
||||||
|
connectRequested[socketId] = false
|
||||||
|
sendStatus(0x03, socketId, 1)
|
||||||
|
log.warn("Socket", socketId, "connect failed")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 连接成功
|
||||||
clients[socketId].socket = sock
|
clients[socketId].socket = sock
|
||||||
clients[socketId].connected = true
|
clients[socketId].connected = true
|
||||||
|
connectRequested[socketId] = false
|
||||||
|
sendStatus(0x01, socketId, 0)
|
||||||
log.info("Socket", socketId, "connected")
|
log.info("Socket", socketId, "connected")
|
||||||
sendConnStatus(0x01, socketId, 0)
|
|
||||||
|
|
||||||
while keepConnecting[socketId] and clients[socketId].connected do
|
-- 监控连接,直到掉线或收到断开命令
|
||||||
local ok = sock:asyncSelect(60, "recv")
|
while clients[socketId].connected
|
||||||
if not ok then
|
and not disconnectRequested[socketId] do
|
||||||
|
-- 检查SIM卡状态,如果SIM卡被拔出则断开连接
|
||||||
|
if not sim.getStatus() then
|
||||||
|
log.warn("Socket", socketId, "SIM card removed, disconnecting")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local alive = sock:asyncSelect(60, "recv")
|
||||||
|
if not alive then
|
||||||
log.warn("Socket", socketId, "connection lost")
|
log.warn("Socket", socketId, "connection lost")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
sys.wait(100)
|
sys.wait(100)
|
||||||
end
|
end
|
||||||
|
until true
|
||||||
|
|
||||||
if clients[socketId].socket then
|
-- 如果还在连接状态说明出了循环 = 掉线或断开
|
||||||
clients[socketId].socket:close()
|
if clients[socketId].connected then
|
||||||
clients[socketId].socket = nil
|
closeSocket(socketId)
|
||||||
end
|
sendStatus(0x02, socketId, 0)
|
||||||
clients[socketId].connected = false
|
log.info("Socket", socketId,
|
||||||
|
"disconnected, waiting reconnect cmd")
|
||||||
if not keepConnecting[socketId] then
|
|
||||||
sendConnStatus(0x02, socketId, 0)
|
|
||||||
break
|
|
||||||
else
|
|
||||||
log.info("Socket", socketId, "will reconnect after 3s")
|
|
||||||
sys.wait(3000)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 订阅底层Socket接收事件
|
-- 监听SIM卡状态变化,SIM卡被拔出时断开所有连接
|
||||||
|
sys.subscribe("SIM_IND", function(para)
|
||||||
|
log.info("SIM_IND received:", para)
|
||||||
|
-- SIM卡未就绪(被拔出或异常)
|
||||||
|
if para ~= "RDY" then
|
||||||
|
for id = 1, MAX_CLIENTS do
|
||||||
|
if clients[id].connected then
|
||||||
|
log.warn("SIM card removed, disconnecting socket", id)
|
||||||
|
closeSocket(id)
|
||||||
|
sendStatus(0x02, id, 3) -- 状态码3表示SIM卡异常导致断开
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- 数据接收
|
||||||
sys.subscribe("SOCKET_RECV", function(socketId)
|
sys.subscribe("SOCKET_RECV", function(socketId)
|
||||||
for i, client in ipairs(clients) do
|
for i, client in ipairs(clients) do
|
||||||
if client.socket and client.socket.id == socketId and client.connected then
|
if client.socket and client.socket.id == socketId and client.connected then
|
||||||
local data = client.socket:asyncRecv()
|
local data = client.socket:asyncRecv()
|
||||||
if data and #data > 0 then
|
if data and #data > 0 and recvCallback then
|
||||||
log.info("Socket", client.id, "received data len=", #data)
|
|
||||||
if recvCallback then
|
|
||||||
recvCallback(client.id, data)
|
recvCallback(client.id, data)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- 模块接口
|
|
||||||
local M = {
|
local M = {
|
||||||
setKeepConnecting = setKeepConnecting,
|
connectSocket = connectSocket,
|
||||||
|
disconnectSocket = disconnectSocket,
|
||||||
sendToSocket = sendToSocket,
|
sendToSocket = sendToSocket,
|
||||||
setRecvCallback = setRecvCallback,
|
setRecvCallback = setRecvCallback,
|
||||||
|
setServerAddress = setServerAddress,
|
||||||
|
getLinkStatus = getLinkStatus,
|
||||||
}
|
}
|
||||||
return M
|
return M
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 5.4 KiB |
@@ -88,6 +88,12 @@
|
|||||||
#define configUSE_CO_ROUTINES 0
|
#define configUSE_CO_ROUTINES 0
|
||||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||||
|
|
||||||
|
/* Software timer definitions. */
|
||||||
|
#define configUSE_TIMERS 1
|
||||||
|
#define configTIMER_TASK_PRIORITY ( 2 )
|
||||||
|
#define configTIMER_QUEUE_LENGTH 10
|
||||||
|
#define configTIMER_TASK_STACK_DEPTH 1024
|
||||||
|
|
||||||
/* Set the following definitions to 1 to include the API function, or zero
|
/* Set the following definitions to 1 to include the API function, or zero
|
||||||
to exclude the API function. */
|
to exclude the API function. */
|
||||||
#define INCLUDE_vTaskPrioritySet 1
|
#define INCLUDE_vTaskPrioritySet 1
|
||||||
@@ -145,6 +151,8 @@ standard names. */
|
|||||||
/* Definitions needed when configGENERATE_RUN_TIME_STATS is on */
|
/* Definitions needed when configGENERATE_RUN_TIME_STATS is on */
|
||||||
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS configureTimerForRunTimeStats
|
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS configureTimerForRunTimeStats
|
||||||
#define portGET_RUN_TIME_COUNTER_VALUE getRunTimeCounterValue
|
#define portGET_RUN_TIME_COUNTER_VALUE getRunTimeCounterValue
|
||||||
|
|
||||||
|
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
/* USER CODE BEGIN Defines */
|
/* USER CODE BEGIN Defines */
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
|
|||||||
/* GetIdleTaskMemory prototype (linked to static allocation support) */
|
/* GetIdleTaskMemory prototype (linked to static allocation support) */
|
||||||
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
|
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
|
||||||
|
|
||||||
|
/* GetTimerTaskMemory prototype (linked to static allocation support) */
|
||||||
|
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );
|
||||||
|
|
||||||
/* Hook prototypes */
|
/* Hook prototypes */
|
||||||
void configureTimerForRunTimeStats(void);
|
void configureTimerForRunTimeStats(void);
|
||||||
unsigned long getRunTimeCounterValue(void);
|
unsigned long getRunTimeCounterValue(void);
|
||||||
@@ -124,6 +127,19 @@ void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackTy
|
|||||||
}
|
}
|
||||||
/* USER CODE END GET_IDLE_TASK_MEMORY */
|
/* USER CODE END GET_IDLE_TASK_MEMORY */
|
||||||
|
|
||||||
|
/* USER CODE BEGIN GET_TIMER_TASK_MEMORY */
|
||||||
|
static StaticTask_t xTimerTaskTCBBuffer;
|
||||||
|
static StackType_t xTimerStack[configTIMER_TASK_STACK_DEPTH];
|
||||||
|
|
||||||
|
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
|
||||||
|
{
|
||||||
|
*ppxTimerTaskTCBBuffer = &xTimerTaskTCBBuffer;
|
||||||
|
*ppxTimerTaskStackBuffer = &xTimerStack[0];
|
||||||
|
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
|
||||||
|
/* place for user code */
|
||||||
|
}
|
||||||
|
/* USER CODE END GET_TIMER_TASK_MEMORY */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief FreeRTOS initialization
|
* @brief FreeRTOS initialization
|
||||||
* @param None
|
* @param None
|
||||||
@@ -152,7 +168,7 @@ void MX_FREERTOS_Init(void) {
|
|||||||
|
|
||||||
/* Create the thread(s) */
|
/* Create the thread(s) */
|
||||||
/* definition and creation of defaultTask */
|
/* definition and creation of defaultTask */
|
||||||
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 256);
|
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 512);
|
||||||
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
|
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
|
||||||
|
|
||||||
/* USER CODE BEGIN RTOS_THREADS */
|
/* USER CODE BEGIN RTOS_THREADS */
|
||||||
|
|||||||
@@ -117,8 +117,7 @@ int main(void)
|
|||||||
MX_USART6_UART_Init();
|
MX_USART6_UART_Init();
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
MX_DMA_Init();
|
MX_DMA_Init();
|
||||||
g_Init();
|
g_init();
|
||||||
Os_Init();
|
|
||||||
|
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
|
|
||||||
@@ -184,7 +183,7 @@ void SystemClock_Config(void)
|
|||||||
RCC_OscInitStruct.PLL.PLLM = 5;
|
RCC_OscInitStruct.PLL.PLLM = 5;
|
||||||
RCC_OscInitStruct.PLL.PLLN = 192;
|
RCC_OscInitStruct.PLL.PLLN = 192;
|
||||||
RCC_OscInitStruct.PLL.PLLP = 2;
|
RCC_OscInitStruct.PLL.PLLP = 2;
|
||||||
RCC_OscInitStruct.PLL.PLLQ = 15;
|
RCC_OscInitStruct.PLL.PLLQ = 2;
|
||||||
RCC_OscInitStruct.PLL.PLLR = 2;
|
RCC_OscInitStruct.PLL.PLLR = 2;
|
||||||
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
|
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
|
||||||
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
|
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
/* USER CODE BEGIN 0 */
|
/* USER CODE BEGIN 0 */
|
||||||
|
|
||||||
#include "_hal_usart.h"
|
#include "drv_usart.h"
|
||||||
|
|
||||||
/* USER CODE END 0 */
|
/* USER CODE END 0 */
|
||||||
|
|
||||||
|
|||||||
@@ -67,25 +67,28 @@ ETH.RxDescAddress=0x30040000
|
|||||||
ETH.TxDescAddress=0x30040060
|
ETH.TxDescAddress=0x30040060
|
||||||
FREERTOS.INCLUDE_uxTaskGetStackHighWaterMark=1
|
FREERTOS.INCLUDE_uxTaskGetStackHighWaterMark=1
|
||||||
FREERTOS.INCLUDE_vTaskDelayUntil=1
|
FREERTOS.INCLUDE_vTaskDelayUntil=1
|
||||||
FREERTOS.IPParameters=Tasks01,configENABLE_FPU,configUSE_COUNTING_SEMAPHORES,configTOTAL_HEAP_SIZE,configUSE_TICK_HOOK,configUSE_MALLOC_FAILED_HOOK,configGENERATE_RUN_TIME_STATS,configUSE_TRACE_FACILITY,configUSE_STATS_FORMATTING_FUNCTIONS,INCLUDE_vTaskDelayUntil,INCLUDE_uxTaskGetStackHighWaterMark,configMINIMAL_STACK_SIZE
|
FREERTOS.IPParameters=Tasks01,configENABLE_FPU,configUSE_COUNTING_SEMAPHORES,configTOTAL_HEAP_SIZE,configUSE_TICK_HOOK,configUSE_MALLOC_FAILED_HOOK,configGENERATE_RUN_TIME_STATS,configUSE_TRACE_FACILITY,configUSE_STATS_FORMATTING_FUNCTIONS,INCLUDE_vTaskDelayUntil,INCLUDE_uxTaskGetStackHighWaterMark,configMINIMAL_STACK_SIZE,configUSE_TIMERS
|
||||||
FREERTOS.Tasks01=defaultTask,0,256,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
FREERTOS.Tasks01=defaultTask,0,512,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
||||||
FREERTOS.configENABLE_FPU=1
|
FREERTOS.configENABLE_FPU=1
|
||||||
FREERTOS.configGENERATE_RUN_TIME_STATS=1
|
FREERTOS.configGENERATE_RUN_TIME_STATS=1
|
||||||
FREERTOS.configMINIMAL_STACK_SIZE=128
|
FREERTOS.configMINIMAL_STACK_SIZE=512
|
||||||
FREERTOS.configTOTAL_HEAP_SIZE=40960
|
FREERTOS.configTOTAL_HEAP_SIZE=81920
|
||||||
FREERTOS.configUSE_COUNTING_SEMAPHORES=0
|
FREERTOS.configUSE_COUNTING_SEMAPHORES=0
|
||||||
FREERTOS.configUSE_MALLOC_FAILED_HOOK=1
|
FREERTOS.configUSE_MALLOC_FAILED_HOOK=1
|
||||||
FREERTOS.configUSE_STATS_FORMATTING_FUNCTIONS=1
|
FREERTOS.configUSE_STATS_FORMATTING_FUNCTIONS=1
|
||||||
FREERTOS.configUSE_TICK_HOOK=1
|
FREERTOS.configUSE_TICK_HOOK=1
|
||||||
|
FREERTOS.configUSE_TIMERS=1
|
||||||
FREERTOS.configUSE_TRACE_FACILITY=1
|
FREERTOS.configUSE_TRACE_FACILITY=1
|
||||||
File.Version=6
|
File.Version=6
|
||||||
GPIO.groupedBy=Group By Peripherals
|
GPIO.groupedBy=Group By Peripherals
|
||||||
KeepUserPlacement=false
|
KeepUserPlacement=false
|
||||||
LWIP.BSP.number=1
|
LWIP.BSP.number=1
|
||||||
LWIP.CHECKSUM_BY_HARDWARE=0
|
LWIP.CHECKSUM_BY_HARDWARE=0
|
||||||
|
LWIP.DEFAULT_THREAD_STACKSIZE=1024
|
||||||
|
LWIP.DEFAULT_UDP_RECVMBOX_SIZE=40
|
||||||
LWIP.GATEWAY_ADDRESS=010.012.019.001
|
LWIP.GATEWAY_ADDRESS=010.012.019.001
|
||||||
LWIP.IPParameters=LWIP_DHCP,IP_ADDRESS,NETMASK_ADDRESS,GATEWAY_ADDRESS,CHECKSUM_BY_HARDWARE,LWIP_CHECKSUM_CTRL_PER_NETIF,MEMP_NUM_UDP_PCB,MEMP_NUM_TCP_PCB,MEM_SIZE,MEMP_NUM_PBUF,MEMP_MEM_MALLOC,MEMP_MEM_INIT,MEM_LIBC_MALLOC,LWIP_MPU_COMPATIBLE,LWIP_HTTPD,LWIP_HTTPD_SSI_BY_FILE_EXTENSION
|
LWIP.IPParameters=LWIP_DHCP,IP_ADDRESS,NETMASK_ADDRESS,GATEWAY_ADDRESS,CHECKSUM_BY_HARDWARE,LWIP_CHECKSUM_CTRL_PER_NETIF,MEMP_NUM_UDP_PCB,MEMP_NUM_TCP_PCB,MEM_SIZE,MEMP_NUM_PBUF,MEMP_MEM_MALLOC,MEMP_MEM_INIT,MEM_LIBC_MALLOC,LWIP_MPU_COMPATIBLE,LWIP_HTTPD,LWIP_HTTPD_SSI_BY_FILE_EXTENSION,DEFAULT_THREAD_STACKSIZE,TCPIP_MBOX_SIZE,TCPIP_THREAD_STACKSIZE,DEFAULT_UDP_RECVMBOX_SIZE
|
||||||
LWIP.IP_ADDRESS=010.012.019.252
|
LWIP.IP_ADDRESS=010.012.019.100
|
||||||
LWIP.LWIP_CHECKSUM_CTRL_PER_NETIF=1
|
LWIP.LWIP_CHECKSUM_CTRL_PER_NETIF=1
|
||||||
LWIP.LWIP_DHCP=0
|
LWIP.LWIP_DHCP=0
|
||||||
LWIP.LWIP_HTTPD=0
|
LWIP.LWIP_HTTPD=0
|
||||||
@@ -97,8 +100,10 @@ LWIP.MEMP_NUM_PBUF=100
|
|||||||
LWIP.MEMP_NUM_TCP_PCB=10
|
LWIP.MEMP_NUM_TCP_PCB=10
|
||||||
LWIP.MEMP_NUM_UDP_PCB=20
|
LWIP.MEMP_NUM_UDP_PCB=20
|
||||||
LWIP.MEM_LIBC_MALLOC=0
|
LWIP.MEM_LIBC_MALLOC=0
|
||||||
LWIP.MEM_SIZE=1024*10
|
LWIP.MEM_SIZE=1024*20
|
||||||
LWIP.NETMASK_ADDRESS=255.255.255.000
|
LWIP.NETMASK_ADDRESS=255.255.255.000
|
||||||
|
LWIP.TCPIP_MBOX_SIZE=32
|
||||||
|
LWIP.TCPIP_THREAD_STACKSIZE=2048
|
||||||
LWIP.Version=v2.1.2_Cube
|
LWIP.Version=v2.1.2_Cube
|
||||||
LWIP0.BSP.STBoard=false
|
LWIP0.BSP.STBoard=false
|
||||||
LWIP0.BSP.api=BSP_COMPONENT_DRIVER
|
LWIP0.BSP.api=BSP_COMPONENT_DRIVER
|
||||||
@@ -119,6 +124,8 @@ Mcu.IP1=DEBUG
|
|||||||
Mcu.IP10=USART1
|
Mcu.IP10=USART1
|
||||||
Mcu.IP11=USART3
|
Mcu.IP11=USART3
|
||||||
Mcu.IP12=USART6
|
Mcu.IP12=USART6
|
||||||
|
Mcu.IP13=USB_DEVICE
|
||||||
|
Mcu.IP14=USB_OTG_FS
|
||||||
Mcu.IP2=DMA
|
Mcu.IP2=DMA
|
||||||
Mcu.IP3=ETH
|
Mcu.IP3=ETH
|
||||||
Mcu.IP4=FREERTOS
|
Mcu.IP4=FREERTOS
|
||||||
@@ -127,7 +134,7 @@ Mcu.IP6=MEMORYMAP
|
|||||||
Mcu.IP7=NVIC
|
Mcu.IP7=NVIC
|
||||||
Mcu.IP8=RCC
|
Mcu.IP8=RCC
|
||||||
Mcu.IP9=SYS
|
Mcu.IP9=SYS
|
||||||
Mcu.IPNb=13
|
Mcu.IPNb=15
|
||||||
Mcu.Name=STM32H743IITx
|
Mcu.Name=STM32H743IITx
|
||||||
Mcu.Package=LQFP176
|
Mcu.Package=LQFP176
|
||||||
Mcu.Pin0=PC14-OSC32_IN (OSC32_IN)
|
Mcu.Pin0=PC14-OSC32_IN (OSC32_IN)
|
||||||
@@ -141,26 +148,29 @@ Mcu.Pin15=PB12
|
|||||||
Mcu.Pin16=PB13
|
Mcu.Pin16=PB13
|
||||||
Mcu.Pin17=PB14
|
Mcu.Pin17=PB14
|
||||||
Mcu.Pin18=PB15
|
Mcu.Pin18=PB15
|
||||||
Mcu.Pin19=PA13 (JTMS/SWDIO)
|
Mcu.Pin19=PA11
|
||||||
Mcu.Pin2=PH0-OSC_IN (PH0)
|
Mcu.Pin2=PH0-OSC_IN (PH0)
|
||||||
Mcu.Pin20=PA14 (JTCK/SWCLK)
|
Mcu.Pin20=PA12
|
||||||
Mcu.Pin21=PC10
|
Mcu.Pin21=PA13 (JTMS/SWDIO)
|
||||||
Mcu.Pin22=PC11
|
Mcu.Pin22=PA14 (JTCK/SWCLK)
|
||||||
Mcu.Pin23=PC12
|
Mcu.Pin23=PC10
|
||||||
Mcu.Pin24=PG9
|
Mcu.Pin24=PC11
|
||||||
Mcu.Pin25=PG14
|
Mcu.Pin25=PC12
|
||||||
Mcu.Pin26=VP_FREERTOS_VS_CMSIS_V1
|
Mcu.Pin26=PG9
|
||||||
Mcu.Pin27=VP_LWIP_VS_Enabled
|
Mcu.Pin27=PG14
|
||||||
Mcu.Pin28=VP_SYS_VS_tim7
|
Mcu.Pin28=VP_FREERTOS_VS_CMSIS_V1
|
||||||
Mcu.Pin29=VP_MEMORYMAP_VS_MEMORYMAP
|
Mcu.Pin29=VP_LWIP_VS_Enabled
|
||||||
Mcu.Pin3=PH1-OSC_OUT (PH1)
|
Mcu.Pin3=PH1-OSC_OUT (PH1)
|
||||||
|
Mcu.Pin30=VP_SYS_VS_tim7
|
||||||
|
Mcu.Pin31=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS
|
||||||
|
Mcu.Pin32=VP_MEMORYMAP_VS_MEMORYMAP
|
||||||
Mcu.Pin4=PC1
|
Mcu.Pin4=PC1
|
||||||
Mcu.Pin5=PA1
|
Mcu.Pin5=PA1
|
||||||
Mcu.Pin6=PA2
|
Mcu.Pin6=PA2
|
||||||
Mcu.Pin7=PH4
|
Mcu.Pin7=PH4
|
||||||
Mcu.Pin8=PH5
|
Mcu.Pin8=PH5
|
||||||
Mcu.Pin9=PA7
|
Mcu.Pin9=PA7
|
||||||
Mcu.PinsNb=30
|
Mcu.PinsNb=33
|
||||||
Mcu.ThirdPartyNb=0
|
Mcu.ThirdPartyNb=0
|
||||||
Mcu.UserConstants=
|
Mcu.UserConstants=
|
||||||
Mcu.UserName=STM32H743IITx
|
Mcu.UserName=STM32H743IITx
|
||||||
@@ -175,6 +185,7 @@ NVIC.ForceEnableDMAVector=false
|
|||||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
|
NVIC.OTG_FS_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
|
||||||
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
|
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
|
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
|
||||||
@@ -192,6 +203,10 @@ PA1.GPIOParameters=GPIO_Speed
|
|||||||
PA1.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
PA1.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
||||||
PA1.Mode=RMII
|
PA1.Mode=RMII
|
||||||
PA1.Signal=ETH_REF_CLK
|
PA1.Signal=ETH_REF_CLK
|
||||||
|
PA11.Mode=Device_Only
|
||||||
|
PA11.Signal=USB_OTG_FS_DM
|
||||||
|
PA12.Mode=Device_Only
|
||||||
|
PA12.Signal=USB_OTG_FS_DP
|
||||||
PA13\ (JTMS/SWDIO).Mode=Serial_Wire
|
PA13\ (JTMS/SWDIO).Mode=Serial_Wire
|
||||||
PA13\ (JTMS/SWDIO).Signal=DEBUG_JTMS-SWDIO
|
PA13\ (JTMS/SWDIO).Signal=DEBUG_JTMS-SWDIO
|
||||||
PA14\ (JTCK/SWCLK).Mode=Serial_Wire
|
PA14\ (JTCK/SWCLK).Mode=Serial_Wire
|
||||||
@@ -327,7 +342,7 @@ ProjectManager.ToolChainLocation=
|
|||||||
ProjectManager.UAScriptAfterPath=
|
ProjectManager.UAScriptAfterPath=
|
||||||
ProjectManager.UAScriptBeforePath=
|
ProjectManager.UAScriptBeforePath=
|
||||||
ProjectManager.UnderRoot=false
|
ProjectManager.UnderRoot=false
|
||||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_LWIP_Init-LWIP-false-HAL-false,6-MX_USART3_UART_Init-USART3-false-HAL-true,7-MX_USART6_UART_Init-USART6-false-HAL-true,8-MX_FMC_Init-FMC-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true
|
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_LWIP_Init-LWIP-false-HAL-false,6-MX_USART3_UART_Init-USART3-false-HAL-true,7-MX_USART6_UART_Init-USART6-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true
|
||||||
RCC.ADCFreq_Value=50390625
|
RCC.ADCFreq_Value=50390625
|
||||||
RCC.AHB12Freq_Value=240000000
|
RCC.AHB12Freq_Value=240000000
|
||||||
RCC.AHB4Freq_Value=240000000
|
RCC.AHB4Freq_Value=240000000
|
||||||
@@ -367,7 +382,7 @@ RCC.HPRE=RCC_HCLK_DIV2
|
|||||||
RCC.HRTIMFreq_Value=240000000
|
RCC.HRTIMFreq_Value=240000000
|
||||||
RCC.I2C123Freq_Value=120000000
|
RCC.I2C123Freq_Value=120000000
|
||||||
RCC.I2C4Freq_Value=120000000
|
RCC.I2C4Freq_Value=120000000
|
||||||
RCC.IPParameters=ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,D1PPRE,D2PPRE1,D2PPRE2,D3PPRE,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVN1,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3Freq_Value,DIVQ1Freq_Value,DIVQ2Freq_Value,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2Freq_Value,DIVR3Freq_Value,FDCANFreq_Value,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,HPRE,HRTIMFreq_Value,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLLSourceVirtual,PWR_Regulator_Voltage_Scale,ProductRev,QSPIFreq_Value,RCC_TIM_PRescaler_Selection,RNGFreq_Value,RTCFreq_Value,SAI1Freq_Value,SAI23Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,SupplySource,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16Freq_Value,USART234578Freq_Value,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value
|
RCC.IPParameters=ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,D1PPRE,D2PPRE1,D2PPRE2,D3PPRE,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVN1,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3Freq_Value,DIVQ1Freq_Value,DIVQ2Freq_Value,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2Freq_Value,DIVR3Freq_Value,FDCANFreq_Value,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,HPRE,HRTIMFreq_Value,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLLSourceVirtual,PWR_Regulator_Voltage_Scale,ProductRev,QSPIFreq_Value,RCC_TIM_PRescaler_Selection,RNGFreq_Value,RTCFreq_Value,SAI1Freq_Value,SAI23Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,SupplySource,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16Freq_Value,USART234578Freq_Value,USBCLockSelection,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value
|
||||||
RCC.LPTIM1Freq_Value=120000000
|
RCC.LPTIM1Freq_Value=120000000
|
||||||
RCC.LPTIM2Freq_Value=120000000
|
RCC.LPTIM2Freq_Value=120000000
|
||||||
RCC.LPTIM345Freq_Value=120000000
|
RCC.LPTIM345Freq_Value=120000000
|
||||||
@@ -400,7 +415,8 @@ RCC.Tim2OutputFreq_Value=240000000
|
|||||||
RCC.TraceFreq_Value=480000000
|
RCC.TraceFreq_Value=480000000
|
||||||
RCC.USART16Freq_Value=120000000
|
RCC.USART16Freq_Value=120000000
|
||||||
RCC.USART234578Freq_Value=120000000
|
RCC.USART234578Freq_Value=120000000
|
||||||
RCC.USBFreq_Value=480000000
|
RCC.USBCLockSelection=RCC_USBCLKSOURCE_HSI48
|
||||||
|
RCC.USBFreq_Value=48000000
|
||||||
RCC.VCO1OutputFreq_Value=960000000
|
RCC.VCO1OutputFreq_Value=960000000
|
||||||
RCC.VCO2OutputFreq_Value=100781250
|
RCC.VCO2OutputFreq_Value=100781250
|
||||||
RCC.VCO3OutputFreq_Value=100781250
|
RCC.VCO3OutputFreq_Value=100781250
|
||||||
@@ -413,6 +429,12 @@ USART3.IPParameters=VirtualMode-Asynchronous
|
|||||||
USART3.VirtualMode-Asynchronous=VM_ASYNC
|
USART3.VirtualMode-Asynchronous=VM_ASYNC
|
||||||
USART6.IPParameters=VirtualMode-Asynchronous
|
USART6.IPParameters=VirtualMode-Asynchronous
|
||||||
USART6.VirtualMode-Asynchronous=VM_ASYNC
|
USART6.VirtualMode-Asynchronous=VM_ASYNC
|
||||||
|
USB_DEVICE.CLASS_NAME_FS=CDC
|
||||||
|
USB_DEVICE.IPParameters=VirtualMode-CDC_FS,VirtualModeFS,CLASS_NAME_FS
|
||||||
|
USB_DEVICE.VirtualMode-CDC_FS=Cdc
|
||||||
|
USB_DEVICE.VirtualModeFS=Cdc_FS
|
||||||
|
USB_OTG_FS.IPParameters=VirtualMode
|
||||||
|
USB_OTG_FS.VirtualMode=Device_Only
|
||||||
VP_FREERTOS_VS_CMSIS_V1.Mode=CMSIS_V1
|
VP_FREERTOS_VS_CMSIS_V1.Mode=CMSIS_V1
|
||||||
VP_FREERTOS_VS_CMSIS_V1.Signal=FREERTOS_VS_CMSIS_V1
|
VP_FREERTOS_VS_CMSIS_V1.Signal=FREERTOS_VS_CMSIS_V1
|
||||||
VP_LWIP_VS_Enabled.Mode=Enabled
|
VP_LWIP_VS_Enabled.Mode=Enabled
|
||||||
@@ -421,5 +443,7 @@ VP_MEMORYMAP_VS_MEMORYMAP.Mode=CurAppReg
|
|||||||
VP_MEMORYMAP_VS_MEMORYMAP.Signal=MEMORYMAP_VS_MEMORYMAP
|
VP_MEMORYMAP_VS_MEMORYMAP.Signal=MEMORYMAP_VS_MEMORYMAP
|
||||||
VP_SYS_VS_tim7.Mode=TIM7
|
VP_SYS_VS_tim7.Mode=TIM7
|
||||||
VP_SYS_VS_tim7.Signal=SYS_VS_tim7
|
VP_SYS_VS_tim7.Signal=SYS_VS_tim7
|
||||||
|
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Mode=CDC_FS
|
||||||
|
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS
|
||||||
board=custom
|
board=custom
|
||||||
rtos.0.ip=FREERTOS
|
rtos.0.ip=FREERTOS
|
||||||
|
|||||||
@@ -928,7 +928,7 @@ void ethernet_link_thread(void const * argument)
|
|||||||
|
|
||||||
/* USER CODE BEGIN ETH link Thread core code for User BSP */
|
/* USER CODE BEGIN ETH link Thread core code for User BSP */
|
||||||
#else
|
#else
|
||||||
bool lwip_initialized = false;
|
// bool lwip_initialized = false;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
@@ -983,12 +983,12 @@ void ethernet_link_thread(void const * argument)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lwip_initialized == false)
|
// if (lwip_initialized == false)
|
||||||
{
|
// {
|
||||||
|
|
||||||
xTaskNotifyGive(DownLinkTaskHandle);
|
// xTaskNotifyGive(DownLinkTaskHandle);
|
||||||
lwip_initialized = true;
|
// lwip_initialized = true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* USER CODE END ETH link Thread core code for User BSP */
|
/* USER CODE END ETH link Thread core code for User BSP */
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
/*----- Value in opt.h for DEFAULT_UDP_RECVMBOX_SIZE: 0 -----*/
|
/*----- Value in opt.h for DEFAULT_UDP_RECVMBOX_SIZE: 0 -----*/
|
||||||
#define DEFAULT_UDP_RECVMBOX_SIZE 40
|
#define DEFAULT_UDP_RECVMBOX_SIZE 40
|
||||||
/*----- Value in opt.h for DEFAULT_TCP_RECVMBOX_SIZE: 0 -----*/
|
/*----- Value in opt.h for DEFAULT_TCP_RECVMBOX_SIZE: 0 -----*/
|
||||||
#define DEFAULT_TCP_RECVMBOX_SIZE 20
|
#define DEFAULT_TCP_RECVMBOX_SIZE 6
|
||||||
/*----- Value in opt.h for DEFAULT_ACCEPTMBOX_SIZE: 0 -----*/
|
/*----- Value in opt.h for DEFAULT_ACCEPTMBOX_SIZE: 0 -----*/
|
||||||
#define DEFAULT_ACCEPTMBOX_SIZE 6
|
#define DEFAULT_ACCEPTMBOX_SIZE 6
|
||||||
/*----- Value in opt.h for RECV_BUFSIZE_DEFAULT: INT_MAX -----*/
|
/*----- Value in opt.h for RECV_BUFSIZE_DEFAULT: INT_MAX -----*/
|
||||||
|
|||||||
@@ -68,12 +68,13 @@ virtualFolder:
|
|||||||
- name: Config
|
- name: Config
|
||||||
files:
|
files:
|
||||||
- path: ../User/Global/global.h
|
- path: ../User/Global/global.h
|
||||||
|
- path: ../User/Global/board_config.h
|
||||||
folders: []
|
folders: []
|
||||||
- name: Global
|
- name: Global
|
||||||
files:
|
files:
|
||||||
- path: ../User/Global/g_init.c
|
|
||||||
- path: ../User/Global/g_runtime.c
|
- path: ../User/Global/g_runtime.c
|
||||||
- path: ../User/Global/g_dcpile.c
|
- path: ../User/Global/g_dcpile.c
|
||||||
|
- path: ../User/Global/g_init.c
|
||||||
folders: []
|
folders: []
|
||||||
- name: Os
|
- name: Os
|
||||||
files:
|
files:
|
||||||
@@ -81,24 +82,48 @@ virtualFolder:
|
|||||||
- path: ../User/Os/os_task.c
|
- path: ../User/Os/os_task.c
|
||||||
- path: ../User/Os/os_queue.c
|
- path: ../User/Os/os_queue.c
|
||||||
- path: ../User/Os/os_semaphore.c
|
- path: ../User/Os/os_semaphore.c
|
||||||
folders: []
|
- path: ../User/Os/os_timer.c
|
||||||
- name: Hal
|
|
||||||
files:
|
|
||||||
- path: ../User/Hal/_hal_init.c
|
|
||||||
- path: ../User/Hal/_hal_usart.c
|
|
||||||
folders: []
|
folders: []
|
||||||
- name: Driver
|
- name: Driver
|
||||||
files:
|
files:
|
||||||
- path: ../User/Driver/drv_init.c
|
- path: ../User/Driver/drv_init.c
|
||||||
- path: ../User/Driver/drv_flash.c
|
- path: ../User/Driver/drv_flash.c
|
||||||
- path: ../User/Driver/flash_config.c
|
- path: ../User/Driver/flash_config.c
|
||||||
|
- path: ../User/Driver/drv_usart.c
|
||||||
|
- path: ../User/Driver/drv_air724.c
|
||||||
folders: []
|
folders: []
|
||||||
- name: Task
|
- name: App
|
||||||
files:
|
files:
|
||||||
- path: ../User/Task/HeartBeatTask.c
|
- path: ../User/App/task_ykc.c
|
||||||
- path: ../User/Task/DatalinkTask.c
|
- path: ../User/App/task_air724.c
|
||||||
- path: ../User/Task/YkcTask.c
|
- path: ../User/App/task_sys.c
|
||||||
- path: ../User/Task/ChargerTask.c
|
- path: ../User/App/task_udp.c
|
||||||
|
folders: []
|
||||||
|
- name: Network
|
||||||
|
files:
|
||||||
|
- path: ../User/Network/udp_router.c
|
||||||
|
- path: ../User/Network/udp_manager.c
|
||||||
|
folders: []
|
||||||
|
- name: Protocol
|
||||||
|
files: []
|
||||||
|
folders:
|
||||||
|
- name: Ykc
|
||||||
|
files:
|
||||||
|
- path: ../User/Protocol/Ykc/charger_to_server.c
|
||||||
|
- path: ../User/Protocol/Ykc/charger_to_server.h
|
||||||
|
- path: ../User/Protocol/Ykc/server_common.c
|
||||||
|
- path: ../User/Protocol/Ykc/server_common.h
|
||||||
|
- path: ../User/Protocol/Ykc/server_to_charger.c
|
||||||
|
- path: ../User/Protocol/Ykc/server_to_charger.h
|
||||||
|
- path: ../User/Protocol/Ykc/ykc_router.c
|
||||||
|
folders: []
|
||||||
|
- name: Point
|
||||||
|
files:
|
||||||
|
- path: ../User/Protocol/Point/point_protocol.c
|
||||||
|
folders: []
|
||||||
|
- name: Host Computer
|
||||||
|
files:
|
||||||
|
- path: ../User/Protocol/Host Computer/host_computer_protocol.c
|
||||||
folders: []
|
folders: []
|
||||||
- name: Drivers
|
- name: Drivers
|
||||||
files: []
|
files: []
|
||||||
@@ -259,12 +284,6 @@ virtualFolder:
|
|||||||
- path: ../Middlewares/Third_Party/LwIP/system/OS/sys_arch.c
|
- path: ../Middlewares/Third_Party/LwIP/system/OS/sys_arch.c
|
||||||
- path: ../Middlewares/Third_Party/LwIP/src/apps/mqtt/mqtt.c
|
- path: ../Middlewares/Third_Party/LwIP/src/apps/mqtt/mqtt.c
|
||||||
folders: []
|
folders: []
|
||||||
- name: Ykc
|
|
||||||
files:
|
|
||||||
- path: ../Middlewares/Third_Party/Ykc/charger_to_server.c
|
|
||||||
- path: ../Middlewares/Third_Party/Ykc/server_common.c
|
|
||||||
- path: ../Middlewares/Third_Party/Ykc/server_to_charger.c
|
|
||||||
folders: []
|
|
||||||
- name: cJSON
|
- name: cJSON
|
||||||
files:
|
files:
|
||||||
- path: ../Middlewares/Third_Party/cJSON/cJSON.c
|
- path: ../Middlewares/Third_Party/cJSON/cJSON.c
|
||||||
@@ -295,8 +314,6 @@ targets:
|
|||||||
- ../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS
|
- ../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS
|
||||||
- ../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F
|
- ../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F
|
||||||
- ../User/Driver
|
- ../User/Driver
|
||||||
- ../User/Hal
|
|
||||||
- ../User/Task
|
|
||||||
- ../User/Os
|
- ../User/Os
|
||||||
- ../LWIP/App
|
- ../LWIP/App
|
||||||
- ../LWIP/Target
|
- ../LWIP/Target
|
||||||
@@ -324,6 +341,11 @@ targets:
|
|||||||
- ../USB_DEVICE/Target
|
- ../USB_DEVICE/Target
|
||||||
- ../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc
|
- ../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc
|
||||||
- ../Middlewares/ST/STM32_USB_Device_Library/Core/Inc
|
- ../Middlewares/ST/STM32_USB_Device_Library/Core/Inc
|
||||||
|
- ../User/Protocol/Ykc
|
||||||
|
- ../User/Protocol/Point
|
||||||
|
- ../User/Protocol/Host Computer
|
||||||
|
- ../User/Network
|
||||||
|
- ../User/App
|
||||||
libList: []
|
libList: []
|
||||||
excludeList:
|
excludeList:
|
||||||
- <virtual_root>/User/Hal/_hal_myi2c.c
|
- <virtual_root>/User/Hal/_hal_myi2c.c
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,2 @@
|
|||||||
### 生产代码设置
|
### 生产代码设置
|
||||||
- /User/Global/g_decpile -> void init_chargers(void) 需要修改预设 ,从电桩全局结构体拿
|
- /User/Global/g_decpile -> void init_chargers(void) 需要修改预设 ,从电桩全局结构体拿
|
||||||

|
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "usbd_cdc_if.h"
|
#include "usbd_cdc_if.h"
|
||||||
|
|
||||||
/* USER CODE BEGIN INCLUDE */
|
/* USER CODE BEGIN INCLUDE */
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
/* USER CODE END INCLUDE */
|
/* USER CODE END INCLUDE */
|
||||||
|
|
||||||
@@ -317,6 +318,21 @@ static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
|
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
|
||||||
|
void USB_Printf(const char *format, ...)
|
||||||
|
{
|
||||||
|
char tx_buffer[256];
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
int len = vsnprintf(tx_buffer, sizeof(tx_buffer), format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (len > 0 && len < sizeof(tx_buffer))
|
||||||
|
{
|
||||||
|
CDC_Transmit_FS((uint8_t*)tx_buffer, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
|
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
/* USER CODE BEGIN INCLUDE */
|
/* USER CODE BEGIN INCLUDE */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* USER CODE END INCLUDE */
|
/* USER CODE END INCLUDE */
|
||||||
|
|
||||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||||
@@ -109,6 +111,9 @@ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
|
|||||||
|
|
||||||
/* USER CODE BEGIN EXPORTED_FUNCTIONS */
|
/* USER CODE BEGIN EXPORTED_FUNCTIONS */
|
||||||
|
|
||||||
|
void USB_Printf(const char *format, ...);
|
||||||
|
|
||||||
|
|
||||||
/* USER CODE END EXPORTED_FUNCTIONS */
|
/* USER CODE END EXPORTED_FUNCTIONS */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -62,11 +62,11 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define USBD_VID 1156
|
#define USBD_VID 1155
|
||||||
#define USBD_LANGID_STRING 1033
|
#define USBD_LANGID_STRING 1033
|
||||||
#define USBD_MANUFACTURER_STRING "JSBR"
|
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
|
||||||
#define USBD_PID_FS 22337
|
#define USBD_PID_FS 22336
|
||||||
#define USBD_PRODUCT_STRING_FS "YKC Virtual ComPort"
|
#define USBD_PRODUCT_STRING_FS "STM32 Virtual ComPort"
|
||||||
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
|
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
|
||||||
#define USBD_INTERFACE_STRING_FS "CDC Interface"
|
#define USBD_INTERFACE_STRING_FS "CDC Interface"
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
* @file udp_manager.c
|
||||||
* @file user\task\DatalinkTask.c
|
* @brief UDP管理模块
|
||||||
* @author luhuaishuai
|
* @details 处理充电桩与服务器之间的UDP通信,提供数据发送功能。
|
||||||
* @version v0.1
|
* 支持向指定充电桩发送数据以及向上位机服务器发送数据。
|
||||||
* @date 2026-1-12
|
* @date 2025-01-09 14:32:15
|
||||||
* @brief 数据链路任务,负责处理与云快充的通信
|
* @version 1.0.0
|
||||||
******************************************************************************
|
* @copyright Copyright (c) 2026
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
/* Includes ------------------------------------------------------------------*/
|
||||||
#include "DataLinkTask.h"
|
#include "task_air724.h"
|
||||||
#include "YkcTask.h"
|
#include "ykc_router.h"
|
||||||
#include "lwip/opt.h"
|
#include "drv_air724.h"
|
||||||
#include "lwip/api.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "httpd.h"
|
|
||||||
|
|
||||||
/* typedef --------------------------------------------------------------------*/
|
/* typedef --------------------------------------------------------------------*/
|
||||||
|
|
||||||
@@ -23,7 +20,7 @@
|
|||||||
/* code -----------------------------------------------------------------------*/
|
/* code -----------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief DownLinkTask_Function:
|
* @brief tcp_recv_task_function:云快充 TCP 消息解析任务
|
||||||
*
|
*
|
||||||
* @note none
|
* @note none
|
||||||
*
|
*
|
||||||
@@ -32,11 +29,10 @@
|
|||||||
* @retval runtime : 任务周期
|
* @retval runtime : 任务周期
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DownLinkTask_Function(void const *argument)
|
void air724_recv_task_function(void const *argument)
|
||||||
{
|
{
|
||||||
|
|
||||||
uint8_t air724_rx_msg[UART1_RX_BUFFER_SIZE];
|
uint8_t air724_rx_msg[UART1_RX_BUFFER_SIZE];
|
||||||
uint8_t rs485_rx_msg[UART3_RX_BUFFER_SIZE];
|
|
||||||
uint8_t *ykc_downlink_frame = NULL;
|
uint8_t *ykc_downlink_frame = NULL;
|
||||||
/* 等待 datalink_conn 初始化完成 */
|
/* 等待 datalink_conn 初始化完成 */
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
@@ -56,7 +52,7 @@ void DownLinkTask_Function(void const *argument)
|
|||||||
// 主指令解析
|
// 主指令解析
|
||||||
switch (air724_rx_msg[2])
|
switch (air724_rx_msg[2])
|
||||||
{
|
{
|
||||||
// 云快冲下行解析
|
// 云快充下行解析
|
||||||
case 0x01:
|
case 0x01:
|
||||||
{
|
{
|
||||||
uint8_t charger_index = air724_rx_msg[3];
|
uint8_t charger_index = air724_rx_msg[3];
|
||||||
@@ -73,39 +69,22 @@ void DownLinkTask_Function(void const *argument)
|
|||||||
memcpy(frame.data, ykc_downlink_frame + HEADER_LENGTH, frame.len - 4);
|
memcpy(frame.data, ykc_downlink_frame + HEADER_LENGTH, frame.len - 4);
|
||||||
frame.crc = (ykc_downlink_frame[HEADER_LENGTH + frame.len] << 8) | ykc_downlink_frame[HEADER_LENGTH + frame.len + 1];
|
frame.crc = (ykc_downlink_frame[HEADER_LENGTH + frame.len] << 8) | ykc_downlink_frame[HEADER_LENGTH + frame.len + 1];
|
||||||
|
|
||||||
// printf("Raw Bytes: ");
|
ykc_route_dispatch(charger_index, &frame); // 云快充路由分发
|
||||||
// for (int i = 0; i < ykc_downlink_frame_len; i++)
|
|
||||||
// {
|
|
||||||
// printf("%02X ", ykc_downlink_frame[i]);
|
|
||||||
// if ((i + 1) % 16 == 0) // 每16字节换行
|
|
||||||
// {
|
|
||||||
// printf("\r");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// printf("\r");
|
|
||||||
|
|
||||||
handle_ykc_downlink(charger_index, &frame);
|
|
||||||
|
|
||||||
vPortFree(frame.data);
|
vPortFree(frame.data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x83:
|
case 0x83:
|
||||||
|
case 0x84:
|
||||||
|
case 0x85:
|
||||||
|
case 0x86:
|
||||||
|
case 0x87:
|
||||||
{
|
{
|
||||||
if (air724_rx_msg[3] == 0x01)
|
drv_air724_parse_response(air724_rx_msg, UART1_RX_BUFFER_SIZE);
|
||||||
printf("4G:Socket %d 通道连接成功\r\n", air724_rx_msg[4]);
|
|
||||||
if (air724_rx_msg[3] == 0x02)
|
|
||||||
printf("4G:Socket %d 通道断开成功\r\n", air724_rx_msg[4]);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xQueueReceive(RS485_Message_Queue, &rs485_rx_msg, 10) == pdPASS)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("rs-485_rx_msg: %s", rs485_rx_msg);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
#ifndef __DATALINKTASK_H
|
#ifndef __AIR724_RECV_TASK_H
|
||||||
#define __DATALINKTASK_H
|
#define __AIR724_RECV_TASK_H
|
||||||
|
|
||||||
/* includes ----------------------------------------------------------------------------------------------*/
|
/* includes ----------------------------------------------------------------------------------------------*/
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
@@ -10,9 +10,7 @@
|
|||||||
|
|
||||||
/* struct ------------------------------------------------------------------------------------------------*/
|
/* struct ------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void DataLink_Task_Init(void);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __DATALINKTASK_H */
|
#endif /* __AIR724_RECV_TASK_H */
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
/* Includes ------------------------------------------------------------------*/
|
||||||
#include "HeartBeatTask.h"
|
#include "task_sys.h"
|
||||||
|
|
||||||
void HeartBeat_Sign(void);
|
void HeartBeat_Sign(void);
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ void HeartBeat_Sign(void);
|
|||||||
* @param : argument
|
* @param : argument
|
||||||
* @retval: void
|
* @retval: void
|
||||||
*/
|
*/
|
||||||
void HeartbeatTask_Function(void const *argument)
|
void sys_task_function(void const *argument)
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -58,14 +58,14 @@ void HeartBeat_Sign(void)
|
|||||||
if ((now - last_heartbeat_tick[i]) >= 8000)
|
if ((now - last_heartbeat_tick[i]) >= 8000)
|
||||||
{
|
{
|
||||||
last_heartbeat_tick[i] = now;
|
last_heartbeat_tick[i] = now;
|
||||||
charger_to_server_0X03(i + 1, 1, 0);
|
charger_to_server_0X03(i + 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (any_online)
|
if (any_online)
|
||||||
{
|
{
|
||||||
RUN_EVERY(100, tick_B, {
|
RUN_EVERY(50, tick_B, {
|
||||||
System_Mode_Led_Toggle();
|
System_Mode_Led_Toggle();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef __HEATBEATTASK_H
|
#ifndef __TASK_SYS_H
|
||||||
#define __HEATBEATTASK_H
|
#define __TASK_SYS_H
|
||||||
|
|
||||||
/* includes ----------------------------------------------------------------------------------------------*/
|
/* includes ----------------------------------------------------------------------------------------------*/
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
@@ -19,4 +19,4 @@
|
|||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#endif /* __HEATBEATTASK_H */
|
#endif /* __TASK_SYS_H */
|
||||||
123
Core/User/App/task_udp.c
Normal file
123
Core/User/App/task_udp.c
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/**
|
||||||
|
* @file task_udp.c
|
||||||
|
* @brief UDP通信任务处理模块
|
||||||
|
* @details 处理充电桩与服务器之间的UDP通信协议,包括UDP数据接收、数据解析和路由分发等功能。
|
||||||
|
* 支持JSON格式的数据交互,通过FreeRTOS任务和队列机制实现异步数据处理。
|
||||||
|
* 包含两个主要任务:UDP数据接收任务(udp_recv_task_function)和UDP数据解析任务(udp_parse_task_function)。
|
||||||
|
* @date 2025-01-09 14:32:15
|
||||||
|
* @version 1.0.0
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "task_udp.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief udp_recv_task:UDP 数据接受任务
|
||||||
|
*
|
||||||
|
* @note none
|
||||||
|
*
|
||||||
|
* @param taskID : 任务ID
|
||||||
|
*
|
||||||
|
* @retval runtime : 任务周期
|
||||||
|
*/
|
||||||
|
|
||||||
|
void udp_recv_task_function(void const *argument)
|
||||||
|
{
|
||||||
|
err_t recv_err;
|
||||||
|
struct netbuf *datalink_buf = NULL;
|
||||||
|
datalink_conn = netconn_new(NETCONN_UDP);
|
||||||
|
netconn_bind(datalink_conn, IP_ADDR_ANY, LINK_SERVER_PORT);
|
||||||
|
UDP_Message_Queue_Init(); // 初始化UDP接收队列
|
||||||
|
/*桩UDP通讯初始化完成 发送云快充任务通知*/
|
||||||
|
xTaskNotifyGive(YkcTaskHandle);
|
||||||
|
xTaskNotifyGive(Air724_ParseTaskHandle);
|
||||||
|
xTaskNotifyGive(UDP_ParseTaskHandle);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/*获取任务运行状态*/
|
||||||
|
TaskRunTimeStat.UPLinkTask.threads_runtime = GetTask_RunTime(UPLinkTaskID);
|
||||||
|
TaskRunTimeStat.UPLinkTask.threads_counter = GetTask_Beatcnt(UPLinkTaskID);
|
||||||
|
TaskRunTimeStat.UPLinkTask.threads_freestack = Get_Free_Stack(UPLinkTaskID);
|
||||||
|
|
||||||
|
recv_err = netconn_recv(datalink_conn, &datalink_buf);
|
||||||
|
|
||||||
|
if (recv_err == ERR_OK && datalink_buf != NULL)
|
||||||
|
{
|
||||||
|
uint8_t *playload;
|
||||||
|
uint16_t playload_len;
|
||||||
|
netbuf_data(datalink_buf, (void *)&playload, &playload_len);
|
||||||
|
if (playload_len > 0)
|
||||||
|
{
|
||||||
|
UdpMsg_t msg;
|
||||||
|
ip_addr_copy(msg.src_ip, *netbuf_fromaddr(datalink_buf)); // 获取UDP源IP
|
||||||
|
msg.src_port = netbuf_fromport(datalink_buf); // 获取UDP源端口
|
||||||
|
msg.len = playload_len;
|
||||||
|
msg.data = (char *)pvPortMalloc(playload_len + 1);
|
||||||
|
if (msg.data != NULL)
|
||||||
|
{
|
||||||
|
memcpy(msg.data, playload, playload_len);
|
||||||
|
msg.data[playload_len] = '\0';
|
||||||
|
// 队列满,释放数据内存
|
||||||
|
if (xQueueSend(UDP_Message_Queue, &msg, 0) != pdPASS)
|
||||||
|
{
|
||||||
|
vPortFree(msg.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
netbuf_delete(datalink_buf); // 释放UDP网络缓冲区
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (recv_err != ERR_TIMEOUT && recv_err != ERR_WOULDBLOCK)
|
||||||
|
{
|
||||||
|
printf("datalink netconn_recv err: %d\r\n", recv_err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief UDP_ParseTask_Function:UDP 数据解析任务
|
||||||
|
*
|
||||||
|
* @note none
|
||||||
|
*
|
||||||
|
* @param taskID : 任务ID
|
||||||
|
*
|
||||||
|
* @retval runtime : 任务周期
|
||||||
|
*/
|
||||||
|
void udp_parse_task_function(void const *argument)
|
||||||
|
{
|
||||||
|
UdpMsg_t msg;
|
||||||
|
cJSON *root = NULL, *cmd = NULL, *id = NULL;
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); /* 等待桩通讯协议层完成*/
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (xQueueReceive(UDP_Message_Queue, &msg, portMAX_DELAY) == pdPASS)
|
||||||
|
{
|
||||||
|
root = cJSON_Parse((const char *)msg.data);
|
||||||
|
if (root == NULL)
|
||||||
|
{
|
||||||
|
printf("JSON Parse Failed: %s\r\n", msg.data);
|
||||||
|
vPortFree(msg.data);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
id = cJSON_GetObjectItem(root, "id");
|
||||||
|
cmd = cJSON_GetObjectItem(root, "cmd");
|
||||||
|
|
||||||
|
if (cmd != NULL && id != NULL)
|
||||||
|
{
|
||||||
|
const char *cmd_str = cmd->valuestring;
|
||||||
|
udp_route_dispatch((uint8_t)id->valueint, cmd->valuestring, root); //送入路由处理
|
||||||
|
cJSON_Delete(root);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Missing 'code' field from \r\n");
|
||||||
|
cJSON_Delete(root);
|
||||||
|
}
|
||||||
|
vPortFree(msg.data);
|
||||||
|
msg.data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
Core/User/App/task_udp.h
Normal file
25
Core/User/App/task_udp.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
#ifndef __UDP_TASK_H
|
||||||
|
#define __UDP_TASK_H
|
||||||
|
|
||||||
|
/* includes ----------------------------------------------------------------------------------------------*/
|
||||||
|
#include "global.h"
|
||||||
|
#include "board_config.h"
|
||||||
|
#include "udp_router.h"
|
||||||
|
#include "udp_manager.h"
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/api.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include "httpd.h"
|
||||||
|
|
||||||
|
// 定义UDP消息体
|
||||||
|
typedef struct {
|
||||||
|
ip4_addr_t src_ip; // 来源IP
|
||||||
|
uint16_t src_port; // 来源端口
|
||||||
|
uint16_t len; // 数据长度
|
||||||
|
char *data; // 数据指针(动态分配)
|
||||||
|
} UdpMsg_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __UDP_TASK_H */
|
||||||
197
Core/User/App/task_ykc.c
Normal file
197
Core/User/App/task_ykc.c
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file user\task\HeartBeatTask.c
|
||||||
|
* @author luhuaishuai
|
||||||
|
* @version v0.1
|
||||||
|
* @date 2026-1-12
|
||||||
|
* @brief Briefly describe the function of your function
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "task_ykc.h"
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/api.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include "usbd_cdc_if.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @funNm : ykc_task_function
|
||||||
|
* @brief : 云快充平台交互主任务
|
||||||
|
* @param : argument
|
||||||
|
* @retval: void
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ykc_task_function(void const *argument)
|
||||||
|
{
|
||||||
|
uint32_t now;
|
||||||
|
|
||||||
|
init_chargers();
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
osDelay(5000);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
TaskRunTimeStat.YkcTask.threads_runtime = GetTask_RunTime(YkcTaskID);
|
||||||
|
TaskRunTimeStat.YkcTask.threads_counter = GetTask_Beatcnt(YkcTaskID);
|
||||||
|
TaskRunTimeStat.YkcTask.threads_freestack = Get_Free_Stack(YkcTaskID);
|
||||||
|
|
||||||
|
now = HAL_GetTick();
|
||||||
|
|
||||||
|
for (int i = 0; i < g_charger_manager.charger_count; i++)
|
||||||
|
{
|
||||||
|
ChargerPile *pile = &g_charger_manager.charger_piles[i];
|
||||||
|
|
||||||
|
/* ========== 桩层初始化(桩0~2通用,只做一次) ========== */
|
||||||
|
if (pile->step < 3)
|
||||||
|
{
|
||||||
|
if (now < pile->step_tick)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (pile->step)
|
||||||
|
{
|
||||||
|
case 0: // 等待桩上电 + 连接本桩4G通道
|
||||||
|
{
|
||||||
|
// if (pile->is_udp_online)
|
||||||
|
if(1)
|
||||||
|
{
|
||||||
|
if (!g_air724_info.socket_connected[i])
|
||||||
|
{
|
||||||
|
drv_air724_connect_channel(i + 1);
|
||||||
|
pile->step_tick = now + 3000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pile->step = 1;
|
||||||
|
pile->step_tick = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
USB_Printf("网关:等待桩%d上电指令\r\n", i + 1);
|
||||||
|
drv_air724_query_iccid();
|
||||||
|
pile->step_tick = now + 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // 云快充登录认证
|
||||||
|
{
|
||||||
|
if (!pile->is_online)
|
||||||
|
{
|
||||||
|
charger_to_server_0X01(i + 1);
|
||||||
|
pile->step_tick = now + 5000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pile->step = 2;
|
||||||
|
charger_to_server_0X05(1, i + 1);
|
||||||
|
pile->step_tick = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // 云快充计费模型请求
|
||||||
|
{
|
||||||
|
if (!pile->get_model)
|
||||||
|
{
|
||||||
|
charger_to_server_0X09(i + 1);
|
||||||
|
pile->step_tick = now + 5000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pile->step = 3;
|
||||||
|
pile->step_tick = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== 枪层独立运行(每把枪独立状态机) ========== */
|
||||||
|
for (int g = 0; g < MAX_GUN_PER_CHARGER; g++)
|
||||||
|
{
|
||||||
|
ChargerGun *gun = &pile->guns[g];
|
||||||
|
|
||||||
|
if (now < gun->gun_step_tick)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (gun->gun_step)
|
||||||
|
{
|
||||||
|
case 0: // 运行时:周期上传实时数据 + 账单处理
|
||||||
|
{
|
||||||
|
charger_to_server_0X13(i + 1, g + 1);
|
||||||
|
host_computer_report_data(i + 1, g + 1);
|
||||||
|
|
||||||
|
if (gun->is_get_bill)
|
||||||
|
{
|
||||||
|
charger_to_server_0X3B(i + 1, g + 1);
|
||||||
|
charger_to_server_0X3B(i + 1, g + 1);
|
||||||
|
gun->is_get_bill = 0;
|
||||||
|
memset(gun->real_time_data.trade_serial, 0,
|
||||||
|
sizeof(gun->real_time_data.trade_serial));
|
||||||
|
}
|
||||||
|
gun->gun_step_tick = now + 5000;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
osDelay(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 云快充平台状态检查回调
|
||||||
|
* @note 每 500ms 触发一次,遍历 1-6 号桩检查状态
|
||||||
|
* @param xTimer 定时器句柄
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ykc_timer_callback_function(TimerHandle_t xTimer)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_CHARGER_COUNT; i++)
|
||||||
|
{
|
||||||
|
for (int g = 0; g < MAX_GUN_PER_CHARGER; g++)
|
||||||
|
{
|
||||||
|
ChargerGun *gun = &g_charger_manager.charger_piles[i].guns[g];
|
||||||
|
if (gun->charger_state == REDAY_CHARGER_START_STATE)
|
||||||
|
{
|
||||||
|
USB_Printf("状态机:[info] 桩%d 枪%d 查询中,等待启动回复.... \r\n", i + 1, g + 1);
|
||||||
|
}
|
||||||
|
else if (gun->charger_state == SUCCESS_CHARGER_STATE)
|
||||||
|
{
|
||||||
|
USB_Printf("状态机:[success] 桩%d 枪%d 启动成功.... \r\n", i + 1, g + 1);
|
||||||
|
gun->charger_state = CHARGER_STATE_CHARGING;
|
||||||
|
}
|
||||||
|
else if (gun->charger_state == FAIL_CHARGER_STATE)
|
||||||
|
{
|
||||||
|
USB_Printf("状态机:[error] 桩%d 枪%d 启动失败.... \r\n", i + 1, g + 1);
|
||||||
|
}
|
||||||
|
else if (gun->charger_state == CHARGER_STATE_CHARGING)
|
||||||
|
{
|
||||||
|
USB_Printf("状态机:[info] 桩%d 枪%d 充电中.... \r\n", i + 1, g + 1);
|
||||||
|
}
|
||||||
|
else if (gun->charger_state == REDAY_CHARGER_STOP_STATE)
|
||||||
|
{
|
||||||
|
USB_Printf("状态机:[info] 桩%d 枪%d 查询中,等待停止回复.... \r\n", i + 1, g + 1);
|
||||||
|
}
|
||||||
|
else if (gun->charger_state == SUCCESS_CHARGER_STOP_STATE)
|
||||||
|
{
|
||||||
|
USB_Printf("状态机:[success] 桩%d 枪%d 停止成功.... \r\n", i + 1, g + 1);
|
||||||
|
}
|
||||||
|
else if (gun->charger_state == FAIL_CHARGER_STOP_STATE)
|
||||||
|
{
|
||||||
|
USB_Printf("状态机:[error] 桩%d 枪%d 停止失败.... \r\n", i + 1, g + 1);
|
||||||
|
}
|
||||||
|
else if (gun->charger_state == CHARGER_STATE_CHARGE_DONE)
|
||||||
|
{
|
||||||
|
printf("状态机:[success] 桩%d 枪%d 计费数据已发送,充电完成.... \r\n", i + 1, g + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Core/User/App/task_ykc.h
Normal file
11
Core/User/App/task_ykc.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef __TASK_YKC_H
|
||||||
|
#define __TASK_YKC_H
|
||||||
|
|
||||||
|
/* includes ----------------------------------------------------------------------------------------------*/
|
||||||
|
#include "global.h"
|
||||||
|
#include "drv_air724.h"
|
||||||
|
|
||||||
|
void ykc_task_function(void const *argument);
|
||||||
|
void ykc_timer_callback_function(TimerHandle_t xTimer);
|
||||||
|
|
||||||
|
#endif /* __TASK_YKC_H */
|
||||||
204
Core/User/Driver/drv_air724.c
Normal file
204
Core/User/Driver/drv_air724.c
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
/**
|
||||||
|
* @file drv_air724.c
|
||||||
|
* @brief 4G模块(AIR724)驱动
|
||||||
|
* @details 提供通道连接/断开、设置服务器地址、查询SIM/信号/链路状态的接口,
|
||||||
|
* 以及统一解析4G模块上行响应帧的入口。
|
||||||
|
*
|
||||||
|
* 协议:55 AA mainCmd subCmd [payload] AA 55
|
||||||
|
*
|
||||||
|
* STM32 → 4G:
|
||||||
|
* 0x03 01 channel 连接请求
|
||||||
|
* 0x03 02 channel 断开请求
|
||||||
|
* 0x04 00 ip+port 设置服务器
|
||||||
|
* 0x05 01|02|03 查询ICCID/IMSI/IMEI
|
||||||
|
* 0x06 00 查询信号
|
||||||
|
* 0x07 00 查询链路
|
||||||
|
*
|
||||||
|
* 4G → STM32 (0x83):
|
||||||
|
* 0x83 01 channel 00 已连接
|
||||||
|
* 0x83 02 channel 00 已断开
|
||||||
|
* 0x83 03 channel 01 连接失败
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "drv_air724.h"
|
||||||
|
#include "drv_usart.h"
|
||||||
|
|
||||||
|
Air724_Info_t g_air724_info = {0};
|
||||||
|
|
||||||
|
/* ── 内部:构造并发送命令帧 ──────────────────────────── */
|
||||||
|
static void drv_air724_send_cmd(uint8_t main_cmd, uint8_t sub_cmd,
|
||||||
|
const uint8_t *payload, uint16_t payload_len)
|
||||||
|
{
|
||||||
|
uint8_t frame[256];
|
||||||
|
uint16_t idx = 0;
|
||||||
|
|
||||||
|
frame[idx++] = 0x55;
|
||||||
|
frame[idx++] = 0xAA;
|
||||||
|
frame[idx++] = main_cmd;
|
||||||
|
frame[idx++] = sub_cmd;
|
||||||
|
|
||||||
|
if (payload && payload_len > 0) {
|
||||||
|
memcpy(&frame[idx], payload, payload_len);
|
||||||
|
idx += payload_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame[idx++] = 0xAA;
|
||||||
|
frame[idx++] = 0x55;
|
||||||
|
|
||||||
|
Air724_Message_Send(frame, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── 发送函数 ──────────────────────────────────────── */
|
||||||
|
|
||||||
|
void drv_air724_set_server(const char *ip, uint16_t port)
|
||||||
|
{
|
||||||
|
if (!ip) return;
|
||||||
|
|
||||||
|
uint8_t payload[128];
|
||||||
|
uint8_t ip_len = (uint8_t)strlen(ip);
|
||||||
|
if (ip_len > 100) ip_len = 100;
|
||||||
|
|
||||||
|
payload[0] = ip_len;
|
||||||
|
memcpy(&payload[1], ip, ip_len);
|
||||||
|
payload[1 + ip_len] = (uint8_t)((port >> 8) & 0xFF);
|
||||||
|
payload[2 + ip_len] = (uint8_t)(port & 0xFF);
|
||||||
|
|
||||||
|
drv_air724_send_cmd(0x04, 0, payload, 3 + ip_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drv_air724_connect_channel(uint8_t channel)
|
||||||
|
{
|
||||||
|
if (channel < 1 || channel > AIR724_SOCKET_MAX) {
|
||||||
|
printf("4G: 通道 %d 无效\r\n", channel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
drv_air724_send_cmd(0x03, 0x01, &channel, 1);
|
||||||
|
printf("4G: 通道 %d 连接请求已发送\r\n", channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drv_air724_disconnect_channel(uint8_t channel)
|
||||||
|
{
|
||||||
|
if (channel < 1 || channel > AIR724_SOCKET_MAX) {
|
||||||
|
printf("4G: 通道 %d 无效\r\n", channel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
drv_air724_send_cmd(0x03, 0x02, &channel, 1);
|
||||||
|
printf("4G: 通道 %d 断开请求已发送\r\n", channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drv_air724_query_iccid(void)
|
||||||
|
{
|
||||||
|
drv_air724_send_cmd(0x05, 0x01, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drv_air724_query_imsi(void)
|
||||||
|
{
|
||||||
|
drv_air724_send_cmd(0x05, 0x02, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drv_air724_query_imei(void)
|
||||||
|
{
|
||||||
|
drv_air724_send_cmd(0x05, 0x03, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drv_air724_query_signal(void)
|
||||||
|
{
|
||||||
|
drv_air724_send_cmd(0x06, 0x00, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drv_air724_query_link_status(void)
|
||||||
|
{
|
||||||
|
drv_air724_send_cmd(0x07, 0x00, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── 统一解析入口 ───────────────────────────────────── */
|
||||||
|
|
||||||
|
void drv_air724_parse_response(const uint8_t *frame, uint16_t len)
|
||||||
|
{
|
||||||
|
if (!frame || len < 7) return;
|
||||||
|
|
||||||
|
uint8_t main_cmd = frame[2];
|
||||||
|
uint8_t sub_cmd = frame[3];
|
||||||
|
|
||||||
|
switch (main_cmd) {
|
||||||
|
|
||||||
|
/* ── 0x83: 连接/断开/失败通知 ── */
|
||||||
|
case 0x83:
|
||||||
|
if (len >= 7) {
|
||||||
|
uint8_t socket_id = frame[4];
|
||||||
|
if (socket_id < 1 || socket_id > AIR724_SOCKET_MAX) break;
|
||||||
|
|
||||||
|
switch (sub_cmd) {
|
||||||
|
case 0x01:
|
||||||
|
g_air724_info.socket_connected[socket_id - 1] = 1;
|
||||||
|
printf("4G: 通道 %d 连接成功\r\n", socket_id);
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
g_air724_info.socket_connected[socket_id - 1] = 0;
|
||||||
|
printf("4G: 通道 %d 已断开\r\n", socket_id);
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
g_air724_info.socket_connected[socket_id - 1] = 0;
|
||||||
|
printf("4G: 通道 %d 连接失败\r\n", socket_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ── 0x84: SIM信息响应 ── */
|
||||||
|
case 0x84: {
|
||||||
|
if (len < 5) break;
|
||||||
|
uint8_t data_len = frame[4];
|
||||||
|
if (data_len == 0 || len < (uint16_t)(5 + data_len)) break;
|
||||||
|
|
||||||
|
switch (sub_cmd) {
|
||||||
|
case 0x01:
|
||||||
|
memcpy(g_air724_info.iccid, &frame[5], data_len < 23 ? data_len : 23);
|
||||||
|
g_air724_info.iccid[data_len < 23 ? data_len : 23] = '\0';
|
||||||
|
printf("4G: ICCID=%s\r\n", g_air724_info.iccid);
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
memcpy(g_air724_info.imsi, &frame[5], data_len < 15 ? data_len : 15);
|
||||||
|
g_air724_info.imsi[data_len < 15 ? data_len : 15] = '\0';
|
||||||
|
printf("4G: IMSI=%s\r\n", g_air724_info.imsi);
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
memcpy(g_air724_info.imei, &frame[5], data_len < 15 ? data_len : 15);
|
||||||
|
g_air724_info.imei[data_len < 15 ? data_len : 15] = '\0';
|
||||||
|
printf("4G: IMEI=%s\r\n", g_air724_info.imei);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── 0x85: 信号强度响应 ── */
|
||||||
|
case 0x85:
|
||||||
|
if (len >= 7) {
|
||||||
|
g_air724_info.csq = frame[4];
|
||||||
|
g_air724_info.ber = frame[5];
|
||||||
|
printf("4G: CSQ=%d, BER=%d\r\n", g_air724_info.csq, g_air724_info.ber);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ── 0x86: 链路状态响应 ── */
|
||||||
|
case 0x86: {
|
||||||
|
uint8_t count = (len - 6) < AIR724_SOCKET_MAX ? (len - 6) : AIR724_SOCKET_MAX;
|
||||||
|
for (uint8_t i = 0; i < count; i++) {
|
||||||
|
g_air724_info.socket_connected[i] = frame[4 + i];
|
||||||
|
}
|
||||||
|
printf("4G: 链路[");
|
||||||
|
for (uint8_t i = 0; i < AIR724_SOCKET_MAX; i++) {
|
||||||
|
printf("%d", g_air724_info.socket_connected[i]);
|
||||||
|
}
|
||||||
|
printf("]\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── 0x87: 服务器配置结果 ── */
|
||||||
|
case 0x87:
|
||||||
|
if (len >= 6) {
|
||||||
|
printf("4G: 服务器配置%s\r\n", frame[4] == 0 ? "成功" : "失败");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Core/User/Driver/drv_air724.h
Normal file
39
Core/User/Driver/drv_air724.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __DRVAIR724_H
|
||||||
|
#define __DRVAIR724_H
|
||||||
|
|
||||||
|
/* includes ----------------------------------------------------------------------------------------------*/
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
/* macro ------------------------------------------------------------------------------------------------*/
|
||||||
|
#define AIR724_SOCKET_MAX 6
|
||||||
|
|
||||||
|
/* struct -----------------------------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
char iccid[24];
|
||||||
|
char imsi[16];
|
||||||
|
char imei[16];
|
||||||
|
uint8_t csq;
|
||||||
|
uint8_t ber;
|
||||||
|
uint8_t socket_connected[AIR724_SOCKET_MAX];
|
||||||
|
} Air724_Info_t;
|
||||||
|
|
||||||
|
/* Exported functions prototypes ------------------------------------------------------------------------*/
|
||||||
|
void drv_all_init(void);
|
||||||
|
|
||||||
|
/* ── 查询发送函数(STM32 → 4G)── */
|
||||||
|
void drv_air724_set_server(const char *ip, uint16_t port);
|
||||||
|
void drv_air724_connect_channel(uint8_t channel);
|
||||||
|
void drv_air724_disconnect_channel(uint8_t channel);
|
||||||
|
void drv_air724_query_iccid(void);
|
||||||
|
void drv_air724_query_imsi(void);
|
||||||
|
void drv_air724_query_imei(void);
|
||||||
|
void drv_air724_query_signal(void);
|
||||||
|
void drv_air724_query_link_status(void);
|
||||||
|
|
||||||
|
/* ── 统一解析入口(4G → STM32)── */
|
||||||
|
void drv_air724_parse_response(const uint8_t *frame, uint16_t len);
|
||||||
|
|
||||||
|
/* Exported constants -----------------------------------------------------------------------------------*/
|
||||||
|
extern Air724_Info_t g_air724_info;
|
||||||
|
|
||||||
|
#endif /* __DRVAIR724_H */
|
||||||
@@ -13,31 +13,6 @@
|
|||||||
#include "flash_config.h"
|
#include "flash_config.h"
|
||||||
|
|
||||||
/* code -----------------------------------------------------------------------*/
|
/* code -----------------------------------------------------------------------*/
|
||||||
void send_cmd_to_air724(uint8_t *cmd, uint16_t len)
|
|
||||||
{
|
|
||||||
Air724_Message_Send(cmd, len);
|
|
||||||
}
|
|
||||||
void send_server_address_to_air724(void)
|
|
||||||
{
|
|
||||||
char ip[] = YKC_SERVER_IP;
|
|
||||||
char port[6];
|
|
||||||
sprintf(port, "%d", YKC_SERVER_PORT);
|
|
||||||
|
|
||||||
uint8_t len = strlen(ip) + 1 + strlen(port);
|
|
||||||
uint8_t config_cmd[256] = {0x55, 0xAA, 0x04, 0x00, len};
|
|
||||||
|
|
||||||
uint8_t pos = 5;
|
|
||||||
memcpy(&config_cmd[pos], ip, strlen(ip));
|
|
||||||
pos += strlen(ip);
|
|
||||||
config_cmd[pos++] = 0x00;
|
|
||||||
memcpy(&config_cmd[pos], port, strlen(port));
|
|
||||||
pos += strlen(port);
|
|
||||||
config_cmd[pos++] = 0xAA;
|
|
||||||
config_cmd[pos++] = 0x55;
|
|
||||||
send_cmd_to_air724(config_cmd, pos);
|
|
||||||
pos = 0;
|
|
||||||
memset(config_cmd, 0, sizeof(config_cmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief drv_all_Init:所有传感器、外设芯片、外部设备初始化
|
* @brief drv_all_Init:所有传感器、外设芯片、外部设备初始化
|
||||||
@@ -49,8 +24,9 @@ void send_server_address_to_air724(void)
|
|||||||
* @retval none
|
* @retval none
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void drv_all_Init(void)
|
void drv_all_init(void)
|
||||||
{
|
{
|
||||||
AIR724_RESET(); /* AIR724 复位 */
|
AIR724_RESET(); /* AIR724 复位 */
|
||||||
stm_flash_init();/* 初始化flash */
|
drv_usart_init();/* 初始化所有串口 */
|
||||||
|
stm_flash_init();/* 初始化flash管理器 */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Exported functions prototypes ------------------------------------------------------------------------*/
|
/* Exported functions prototypes ------------------------------------------------------------------------*/
|
||||||
void drv_all_Init(void);
|
void drv_all_init(void);
|
||||||
|
|
||||||
#endif /* __DRVINIT_H */
|
#endif /* __DRVINIT_H */
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Includes -------------------------------------------------------------------*/
|
/* Includes -------------------------------------------------------------------*/
|
||||||
#include "_hal_usart.h"
|
#include "drv_usart.h"
|
||||||
|
|
||||||
/* variables ------------------------------------------------------------------*/
|
/* variables ------------------------------------------------------------------*/
|
||||||
uint8_t uart1_rx_buffer[UART1_RX_BUFFER_SIZE];
|
uint8_t uart1_rx_buffer[UART1_RX_BUFFER_SIZE];
|
||||||
@@ -70,7 +70,7 @@ void Rs485_Message_Send(uint8_t *data, uint16_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief _hal_usart_Init:所有串口初始化
|
* @brief drv_usart_init:所有串口初始化
|
||||||
*
|
*
|
||||||
* @note none
|
* @note none
|
||||||
*
|
*
|
||||||
@@ -79,7 +79,7 @@ void Rs485_Message_Send(uint8_t *data, uint16_t len)
|
|||||||
* @retval none
|
* @retval none
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void hal_usart_Init(void)
|
void drv_usart_init(void)
|
||||||
{
|
{
|
||||||
air724_tx_mutex = xSemaphoreCreateMutex();
|
air724_tx_mutex = xSemaphoreCreateMutex();
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
#ifndef __HALUSART_H
|
#ifndef __DRV_USART_H
|
||||||
#define __HALUSART_H
|
#define __DRV_USART_H
|
||||||
|
|
||||||
/* Suppress warning messages */
|
/* Suppress warning messages */
|
||||||
#if defined(__CC_ARM)
|
#if defined(__CC_ARM)
|
||||||
@@ -27,9 +27,9 @@ extern uint8_t uart1_tx_buffer[UART1_TX_BUFFER_SIZE];
|
|||||||
extern uint8_t uart3_rx_buffer[UART3_RX_BUFFER_SIZE];
|
extern uint8_t uart3_rx_buffer[UART3_RX_BUFFER_SIZE];
|
||||||
extern uint8_t uart3_tx_buffer[UART3_TX_BUFFER_SIZE];
|
extern uint8_t uart3_tx_buffer[UART3_TX_BUFFER_SIZE];
|
||||||
/* function prototype ------------------------------------------------------------------------------------*/
|
/* function prototype ------------------------------------------------------------------------------------*/
|
||||||
extern void hal_usart_init(void);
|
extern void drv_usart_init(void); // 初始化所有串口
|
||||||
extern void air724_callback_fun(void);
|
extern void air724_callback_fun(void); // 4G数据接收回调函数
|
||||||
extern void rs485_callback_fun(void);
|
extern void rs485_callback_fun(void); // RS485数据接收回调函数
|
||||||
extern void Air724_Message_Send(uint8_t *data, uint16_t len);
|
extern void Air724_Message_Send(uint8_t *data, uint16_t len); // 4G数据发送函数
|
||||||
extern void Rs485_Message_Send(uint8_t *data, uint16_t len);
|
extern void Rs485_Message_Send(uint8_t *data, uint16_t len); // RS485数据发送函数
|
||||||
#endif /* __HALUSART_H */
|
#endif /* __DRV_USART_H */
|
||||||
@@ -102,19 +102,8 @@ uint8_t flash_sector_erase(uint32_t addr)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
flash_manage_t stm_flash_manage = {0};
|
flash_manage_t stm_flash_manage = {0};
|
||||||
|
|
||||||
/* demo */
|
|
||||||
// stm_flash_read(data[0], 1);
|
|
||||||
// stm_flash_read(data[1], 0);
|
|
||||||
// stm_flash_read(data[0], 1);
|
|
||||||
// stm_flash_read(data[1], 0);
|
|
||||||
// stm_flash_write("12345678912345678912345678912345678912345", 41, 1);
|
|
||||||
// stm_flash_write("abcdef", 6, 0);
|
|
||||||
// stm_flash_write("12345678912345678912345678912345678912345", 41, 1);
|
|
||||||
// stm_flash_write("abcdef", 6, 0);
|
|
||||||
|
|
||||||
void stm_flash_init(void)
|
void stm_flash_init(void)
|
||||||
{
|
{
|
||||||
stm_flash_manage.align_num = 32;
|
stm_flash_manage.align_num = 32;
|
||||||
|
|||||||
19
Core/User/Global/board_config.h
Normal file
19
Core/User/Global/board_config.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file user\global\board_config.h
|
||||||
|
* @author luhuaishuai
|
||||||
|
* @version v0.1
|
||||||
|
* @date 2023-10-11
|
||||||
|
* @brief Briefly describe the function of your function
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
#ifndef __BOARD_CONFIG_H
|
||||||
|
#define __BOARD_CONFIG_H
|
||||||
|
|
||||||
|
/* Private includes ----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define LINK_SERVER_PORT 6001 // 网关UDP服务端口
|
||||||
|
#define LINK_APP_PORT 6002 // 桩通讯端口
|
||||||
|
#define LINK_STAKE_PORT 6001 // 桩通讯端口
|
||||||
|
|
||||||
|
#endif /* __BOARD_CONFIG_H */
|
||||||
@@ -5,31 +5,32 @@ ChargerManager g_charger_manager = {0};
|
|||||||
|
|
||||||
/*充电桩序列号*/
|
/*充电桩序列号*/
|
||||||
const uint8_t piles_serial[6][7] = {
|
const uint8_t piles_serial[6][7] = {
|
||||||
// {0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x01},
|
|
||||||
|
|
||||||
|
{0x32, 0x01, 0x06, 0x01, 0x16, 0x92, 0x45},
|
||||||
|
{0x32, 0x01, 0x06, 0x01, 0x16, 0x92, 0x44},
|
||||||
|
{0x32, 0x01, 0x06, 0x01, 0x16, 0x92, 0x43},
|
||||||
|
{0x32, 0x01, 0x06, 0x01, 0x16, 0x92, 0x42},
|
||||||
{0x32, 0x01, 0x06, 0x01, 0x11, 0x15, 0x58},
|
{0x32, 0x01, 0x06, 0x01, 0x11, 0x15, 0x58},
|
||||||
|
{0x32, 0x01, 0x06, 0x01, 0x11, 0x15, 0x54},
|
||||||
{0x32, 0x01, 0x06, 0x01, 0x11, 0x16, 0x54},
|
|
||||||
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x01},
|
|
||||||
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x02},
|
|
||||||
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x03},
|
|
||||||
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x04},
|
|
||||||
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x05},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化充电桩管理器
|
* @brief 初始化充电桩管理器
|
||||||
* @note 初始化充电桩管理器,设置充电桩数量和每个充电桩的初始状态
|
* @note 初始化充电桩管理器,设置充电桩数量和每个充电桩的初始状态
|
||||||
*/
|
*/
|
||||||
void init_chargers(void) {
|
void init_chargers(void)
|
||||||
|
{
|
||||||
g_charger_manager.charger_count = MAX_CHARGER_COUNT;
|
g_charger_manager.charger_count = MAX_CHARGER_COUNT;
|
||||||
|
|
||||||
for (int i = 0; i < g_charger_manager.charger_count; i++) {
|
for (int i = 0; i < g_charger_manager.charger_count; i++)
|
||||||
|
{
|
||||||
ChargerPile *ctx = &g_charger_manager.charger_piles[i];
|
ChargerPile *ctx = &g_charger_manager.charger_piles[i];
|
||||||
|
memcpy(ctx->charger_serial, piles_serial[i], CHARGER_SERIAL_LENGTH);
|
||||||
memcpy(ctx->login_info.charger_serial, piles_serial[i], 7);
|
memcpy(ctx->login_info.charger_serial, piles_serial[i], CHARGER_SERIAL_LENGTH);
|
||||||
ctx->get_model = false;
|
ctx->get_model = false;
|
||||||
ctx->is_udp_online = false;
|
ctx->is_udp_online = false;
|
||||||
|
ctx->step = 0;
|
||||||
|
ctx->step_tick = 0;
|
||||||
ctx->login_info.charger_type = CHARGER_TYPE_DC;
|
ctx->login_info.charger_type = CHARGER_TYPE_DC;
|
||||||
ctx->login_info.gun_num = MAX_GUN_PER_CHARGER;
|
ctx->login_info.gun_num = MAX_GUN_PER_CHARGER;
|
||||||
ctx->login_info.protocol_ver = 0x10; // V1.6
|
ctx->login_info.protocol_ver = 0x10; // V1.6
|
||||||
@@ -39,8 +40,11 @@ void init_chargers(void) {
|
|||||||
ctx->login_info.tele_factory = 0x00; // 移动
|
ctx->login_info.tele_factory = 0x00; // 移动
|
||||||
|
|
||||||
// 初始化枪
|
// 初始化枪
|
||||||
for (int g = 0; g < ctx->login_info.gun_num; g++) {
|
for (int g = 0; g < ctx->login_info.gun_num; g++)
|
||||||
|
{
|
||||||
ctx->guns[g].gun_index = g + 1;
|
ctx->guns[g].gun_index = g + 1;
|
||||||
|
ctx->guns[g].gun_step = 0;
|
||||||
|
ctx->guns[g].gun_step_tick = 0;
|
||||||
ctx->guns[g].real_time_data.status = 0; // 离线
|
ctx->guns[g].real_time_data.status = 0; // 离线
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,25 +8,49 @@
|
|||||||
#define MAX_CHARGER_COUNT 2 // 充电桩数量
|
#define MAX_CHARGER_COUNT 2 // 充电桩数量
|
||||||
#define MAX_GUN_PER_CHARGER 2 // 每个充电桩最多枪数
|
#define MAX_GUN_PER_CHARGER 2 // 每个充电桩最多枪数
|
||||||
|
|
||||||
|
enum CHARGER_STATE
|
||||||
|
{
|
||||||
|
IDLE_CHARGER_STATE = 0, // 空闲状态
|
||||||
|
REDAY_CHARGER_START_STATE = 1, // 等待桩启动回应
|
||||||
|
SUCCESS_CHARGER_STATE = 2, // 桩启动成功
|
||||||
|
FAIL_CHARGER_STATE = 3, // 桩启动失败
|
||||||
|
CHARGER_STATE_CHARGING = 4, // 桩充电中
|
||||||
|
REDAY_CHARGER_STOP_STATE = 5, // 等待桩停止回应
|
||||||
|
SUCCESS_CHARGER_STOP_STATE = 6, // 桩停止成功
|
||||||
|
FAIL_CHARGER_STOP_STATE = 7, // 桩停止失败
|
||||||
|
CHARGER_STATE_CHARGE_DONE = 8, // 桩充电完成
|
||||||
|
CHARGER_STATE_STOPPED = 9, // 桩主动停止
|
||||||
|
};
|
||||||
|
|
||||||
/* 充电枪结构体*/
|
/* 充电枪结构体*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t gun_index; // 枪索引
|
uint8_t gun_index; // 枪索引
|
||||||
|
uint8_t charger_state; // 枪充电流程状态
|
||||||
|
uint8_t gun_step; // 枪独立状态步进
|
||||||
|
uint32_t gun_step_tick; // 枪非阻塞延时时间戳(ms)
|
||||||
|
uint8_t is_get_bill; // 是否获取账单数据
|
||||||
|
uint8_t trade_serial[TRADE_SERIAL_LENGTH]; // 交易流水号
|
||||||
|
PACK_DATA_0X33 charging_feedback; // 远程启机反馈数据
|
||||||
PACK_DATA_0X13 real_time_data; // 实时数据
|
PACK_DATA_0X13 real_time_data; // 实时数据
|
||||||
|
PACK_DATA_0X03 heartbeat_status_data; // 心跳状态数据
|
||||||
|
PACK_DATA_0X3B fee_data; // 计费数据
|
||||||
|
PACK_DATA_0X23 bms_demand; // 充电过程BMS需求、充电机输出
|
||||||
|
PACK_DATA_0X25 bms_info; // 充电过程BMS信息
|
||||||
|
|
||||||
} ChargerGun;
|
} ChargerGun;
|
||||||
|
|
||||||
/* 单个充电桩结构体*/
|
/* 单个充电桩结构体*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PACK_DATA_0X01 login_info;
|
|
||||||
bool is_online; // 云快充是否连接
|
bool is_online; // 云快充是否连接
|
||||||
bool is_udp_online; // 是否本地在线
|
bool is_udp_online; // 是否本地在线
|
||||||
bool get_model;
|
bool get_model; // 是否获取计费模型
|
||||||
uint16_t last_heartbeat_time; // 最后一次心跳时间
|
uint8_t step; // 桩初始化/运行状态步进
|
||||||
|
uint32_t step_tick; // 非阻塞延时时间戳(ms)
|
||||||
|
PACK_DATA_0X01 login_info; // 登录信息数据
|
||||||
|
uint8_t charger_serial[CHARGER_SERIAL_LENGTH]; // 桩编号
|
||||||
ChargerGun guns[MAX_GUN_PER_CHARGER]; // 充电枪数组
|
ChargerGun guns[MAX_GUN_PER_CHARGER]; // 充电枪数组
|
||||||
|
|
||||||
} ChargerPile;
|
} ChargerPile;
|
||||||
|
|
||||||
/*全局充电桩管理结构体*/
|
/*全局充电桩管理结构体*/
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
/* Includes -------------------------------------------------------------------*/
|
/* Includes -------------------------------------------------------------------*/
|
||||||
#include "drv_init.h"
|
#include "drv_init.h"
|
||||||
#include "_hal_init.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -20,9 +19,9 @@
|
|||||||
* @brief 初始化全局系统
|
* @brief 初始化全局系统
|
||||||
* @note 初始化全局系统,包括HAL层和驱动层的初始化
|
* @note 初始化全局系统,包括HAL层和驱动层的初始化
|
||||||
*/
|
*/
|
||||||
void g_Init(void)
|
void g_init(void)
|
||||||
{
|
{
|
||||||
_hal_all_Init();
|
drv_all_init();
|
||||||
drv_all_Init();
|
os_init();
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Exported functions prototypes ------------------------------------------------------------------------*/
|
/* Exported functions prototypes ------------------------------------------------------------------------*/
|
||||||
void g_Init(void);
|
void g_init(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "semphr.h"
|
#include "semphr.h"
|
||||||
#include "event_groups.h"
|
#include "event_groups.h"
|
||||||
#include "stream_buffer.h"
|
#include "stream_buffer.h"
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
/* Os */
|
/* Os */
|
||||||
#include "os_task.h"
|
#include "os_task.h"
|
||||||
@@ -47,13 +48,13 @@
|
|||||||
#include "server_to_charger.h"
|
#include "server_to_charger.h"
|
||||||
#include "g_dcpile.h"
|
#include "g_dcpile.h"
|
||||||
|
|
||||||
/* _hal */
|
|
||||||
#include "_hal_usart.h"
|
|
||||||
|
|
||||||
/* driver */
|
/* driver */
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
#include "server_common.h"
|
#include "server_common.h"
|
||||||
#include "charger_to_server.h"
|
#include "charger_to_server.h"
|
||||||
|
#include "drv_usart.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* macro ------------------------------------------------------------------------------------------------*/
|
/* macro ------------------------------------------------------------------------------------------------*/
|
||||||
#define ON 1
|
#define ON 1
|
||||||
@@ -73,8 +74,6 @@
|
|||||||
|
|
||||||
#define DEBUG 1 // 调试模式
|
#define DEBUG 1 // 调试模式
|
||||||
|
|
||||||
#define YKC_SERVER_IP "121.43.69.62" // YKC 服务器 IP 地址
|
|
||||||
#define YKC_SERVER_PORT 8767 // YKC 服务器端口号
|
|
||||||
|
|
||||||
/*- I/O 输出-*/
|
/*- I/O 输出-*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* @file user\hal\_hal_init.c
|
|
||||||
* @author luhuaishuai
|
|
||||||
* @version v0.1
|
|
||||||
* @date 2026-1-12
|
|
||||||
* @brief Briefly describe the function of your function
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
|
||||||
#include "_hal_init.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* code -----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @funNm
|
|
||||||
* @brief
|
|
||||||
* @param
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @brief _hal_all_Init:所有外设接口初始化
|
|
||||||
*
|
|
||||||
* @note none
|
|
||||||
*
|
|
||||||
* @param none
|
|
||||||
*
|
|
||||||
* @retval none
|
|
||||||
*/
|
|
||||||
void _hal_all_Init(void)
|
|
||||||
{
|
|
||||||
hal_usart_Init();
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#ifndef __HALINIT_H
|
|
||||||
#define __HALINIT_H
|
|
||||||
|
|
||||||
/* includes ----------------------------------------------------------------------------------------------*/
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Exported functions prototypes ------------------------------------------------------------------------*/
|
|
||||||
void _hal_all_Init(void);
|
|
||||||
|
|
||||||
#endif /* __HALINIT_H */
|
|
||||||
|
|
||||||
97
Core/User/Network/udp_manager.c
Normal file
97
Core/User/Network/udp_manager.c
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* @file udp_manager.c
|
||||||
|
* @brief UDP管理模块
|
||||||
|
* @details 处理充电桩与服务器之间的UDP通信,提供数据发送功能。
|
||||||
|
* 支持向指定充电桩发送数据以及向上位机服务器发送数据。
|
||||||
|
* @date 2025-01-09 14:32:15
|
||||||
|
* @version 1.0.0
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "udp_manager.h"
|
||||||
|
|
||||||
|
struct netconn *datalink_conn; // 数据链路句柄
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 桩IP地址
|
||||||
|
* @note 桩IP地址从10.12.19.101开始递增
|
||||||
|
*/
|
||||||
|
static ip4_addr_t s_point_ip[6] = {
|
||||||
|
IPADDR4_INIT_BYTES(10, 12, 19, 101), /* 桩1 */
|
||||||
|
IPADDR4_INIT_BYTES(10, 12, 19, 102), /* 桩2 */
|
||||||
|
IPADDR4_INIT_BYTES(10, 12, 19, 103), /* 桩3 */
|
||||||
|
IPADDR4_INIT_BYTES(10, 12, 19, 104), /* 桩4 */
|
||||||
|
IPADDR4_INIT_BYTES(10, 12, 19, 105), /* 桩5 */
|
||||||
|
IPADDR4_INIT_BYTES(10, 12, 19, 106), /* 桩6 */
|
||||||
|
};
|
||||||
|
|
||||||
|
static ip4_addr_t s_server_ip = IPADDR4_INIT_BYTES(10, 12, 19, 107); /* 上位机 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief UDP发送
|
||||||
|
* @note 发送数据到指定桩
|
||||||
|
* @param point_id 目标桩ID
|
||||||
|
* @param data 数据指针
|
||||||
|
* @param len 数据长度
|
||||||
|
* @return err_t 错误码
|
||||||
|
*/
|
||||||
|
err_t udp_send_to_point(uint8_t point_id, uint8_t *data, u16_t len)
|
||||||
|
{
|
||||||
|
if (!data || len == 0)
|
||||||
|
{
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!datalink_conn)
|
||||||
|
{
|
||||||
|
return ERR_CLSD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (point_id < 1 || point_id > 6)
|
||||||
|
{
|
||||||
|
return ERR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct netbuf *buf = netbuf_new();
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *buf_data = netbuf_alloc(buf, len);
|
||||||
|
if (!buf_data)
|
||||||
|
{
|
||||||
|
netbuf_delete(buf);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf_data, data, len);
|
||||||
|
err_t err = netconn_sendto(datalink_conn, buf, &s_point_ip[point_id - 1], LINK_STAKE_PORT);
|
||||||
|
netbuf_delete(buf);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t udp_send_to_server(uint8_t *data, uint16_t len)
|
||||||
|
{
|
||||||
|
struct netbuf *buf = netbuf_new();
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
if (!datalink_conn)
|
||||||
|
{
|
||||||
|
return ERR_CLSD;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *buf_data = netbuf_alloc(buf, len); // ← 在 netbuf 内部分配内存
|
||||||
|
if (!buf_data)
|
||||||
|
{
|
||||||
|
netbuf_delete(buf);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf_data, data, len); // ← 拷贝数据,不再依赖外部指针
|
||||||
|
err_t err = netconn_sendto(datalink_conn, buf, &s_server_ip, LINK_APP_PORT);
|
||||||
|
netbuf_delete(buf);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
41
Core/User/Network/udp_manager.h
Normal file
41
Core/User/Network/udp_manager.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file user\network\udp_manager.h
|
||||||
|
* @author luhuaishuai
|
||||||
|
* @version v0.1
|
||||||
|
* @date 2023-10-11
|
||||||
|
* @brief Briefly describe the function of your function
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
#ifndef __UDP_MANAGER_H
|
||||||
|
#define __UDP_MANAGER_H
|
||||||
|
|
||||||
|
/* includes ----------------------------------------------------------------------------------------------*/
|
||||||
|
#include "global.h"
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/api.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include "board_config.h"
|
||||||
|
/* Private includes ----------------------------------------------------------*/
|
||||||
|
extern struct netconn *datalink_conn; // 数据链路句柄
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 发送数据到充电桩
|
||||||
|
* @param point_index 桩编号 1~6
|
||||||
|
* @param data 数据指针
|
||||||
|
* @param len 数据长度
|
||||||
|
*/
|
||||||
|
err_t udp_send_to_point(uint8_t point_index, uint8_t *data, u16_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 发送数据到上位机
|
||||||
|
* @param data 数据指针
|
||||||
|
* @param len 数据长度
|
||||||
|
*/
|
||||||
|
err_t udp_send_to_server(uint8_t *data, uint16_t len);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __UDP_MANAGER_H */
|
||||||
56
Core/User/Network/udp_router.c
Normal file
56
Core/User/Network/udp_router.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* @file udp_router.c
|
||||||
|
* @brief UDP路由分发模块
|
||||||
|
* @details 处理充电桩与服务器之间的UDP通信路由分发,根据指令字符串匹配对应的处理函数。
|
||||||
|
* 支持充电桩南向通信和上位机控制两类路由,通过静态路由表实现高效的指令分发。
|
||||||
|
* @date 2025-01-09 14:32:15
|
||||||
|
* @version 1.0.0
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*/
|
||||||
|
#include "udp_router.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief UDP 路由表
|
||||||
|
*/
|
||||||
|
static const route_entry_t ROUTE_TABLE[] = {
|
||||||
|
/* ── 充电桩南向路由 ── */
|
||||||
|
{"online", point_callback_power_on, " 上电 "},
|
||||||
|
{"heartbeat", point_callback_heartbeat, " 心跳 "},
|
||||||
|
{"start charging", point_callback_start_charging, " 开始充电反馈 "},
|
||||||
|
{"end charging", point_callback_end_charging, " 停止充电反馈 "},
|
||||||
|
{"realtime data", point_callback_realtime_data, " 实时数据 "},
|
||||||
|
{"settlement bill", point_callback_settlement_bill, " 结算账单 "},
|
||||||
|
{"proactive end charging", point_callback_proactive_end_charging, " 桩主动停止充电反馈 "},
|
||||||
|
{"charge process real", point_callback_charge_process, " BMS实时需求 "},
|
||||||
|
{"bms info real", point_callback_bms_info, " BMS实时信息 "},
|
||||||
|
/* ── 上位机路由 ── */
|
||||||
|
{"server_login", (cmd_handler_t)host_computer_on_login, " 上位机登录 "},
|
||||||
|
{"server_get_status", (cmd_handler_t)host_computer_on_get_status, " 获取状态 "},
|
||||||
|
{"server_reboot", (cmd_handler_t)host_computer_on_reboot, " 重启设备 "},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ROUTE_TABLE_SIZE (sizeof(ROUTE_TABLE) / sizeof(ROUTE_TABLE[0]))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 路由分发入口
|
||||||
|
* @param id 指令发送的充电桩ID
|
||||||
|
* @param cmd 指令字符串
|
||||||
|
* @param json_pack JSON格式的指令参数
|
||||||
|
*/
|
||||||
|
void udp_route_dispatch(uint8_t id, const char *cmd, cJSON *json_pack)
|
||||||
|
{
|
||||||
|
if (!cmd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ROUTE_TABLE_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(cmd, ROUTE_TABLE[i].cmd) == 0)
|
||||||
|
{
|
||||||
|
printf("[ UDP 接收路由 ] 指令: %-26s │ 桩ID: %d │ %s \r\n",cmd,id, ROUTE_TABLE[i].desc);
|
||||||
|
ROUTE_TABLE[i].handler(id, json_pack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[ UDP 接收路由 ] = 未知指令: '%s' 桩ID: %d \r\n", cmd, id);
|
||||||
|
}
|
||||||
23
Core/User/Network/udp_router.h
Normal file
23
Core/User/Network/udp_router.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
#ifndef __UDP_ROUTER_H
|
||||||
|
#define __UDP_ROUTER_H
|
||||||
|
|
||||||
|
/* includes ----------------------------------------------------------------------------------------------*/
|
||||||
|
#include "global.h"
|
||||||
|
#include "board_config.h"
|
||||||
|
#include "point_protocol.h"
|
||||||
|
#include "host_computer_protocol.h"
|
||||||
|
|
||||||
|
typedef void (*cmd_handler_t)(uint8_t id, cJSON *json);
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *cmd;
|
||||||
|
cmd_handler_t handler;
|
||||||
|
const char *desc;
|
||||||
|
} route_entry_t;
|
||||||
|
|
||||||
|
|
||||||
|
void udp_route_dispatch(uint8_t id, const char *cmd, cJSON *json_pack);//UDP路由分发入口
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __UDP_ROUTER_H */
|
||||||
@@ -23,10 +23,11 @@
|
|||||||
*
|
*
|
||||||
* @retval none
|
* @retval none
|
||||||
*/
|
*/
|
||||||
void Os_Init(void)
|
void os_init(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
Os_Semaphore_Init();
|
Os_Semaphore_Init();/* 初始化信号量 */
|
||||||
Os_Task_Init();
|
Os_Task_Init();/* 初始化任务 */
|
||||||
|
SwTimer_Init();/* 初始化软件定时器 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Exported functions prototypes ------------------------------------------------------------------------*/
|
/* Exported functions prototypes ------------------------------------------------------------------------*/
|
||||||
void Os_Init(void);
|
void os_init(void);
|
||||||
|
|
||||||
|
|
||||||
/* Exported constants --------------------------------------------------------*/
|
/* Exported constants --------------------------------------------------------*/
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
/* Includes -------------------------------------------------------------------*/
|
/* Includes -------------------------------------------------------------------*/
|
||||||
#include "os_queue.h"
|
#include "os_queue.h"
|
||||||
#include "ChargerTask.h"
|
#include "task_udp.h"
|
||||||
|
|
||||||
/*-内核对象句柄-队列-*/
|
/*-内核对象句柄-队列-*/
|
||||||
QueueHandle_t Air724_Message_Queue = NULL; /* 4G数据接收队列 */
|
QueueHandle_t Air724_Message_Queue = NULL; /* 4G数据接收队列 */
|
||||||
@@ -21,7 +21,7 @@ QueueHandle_t UDP_Message_Queue = NULL; /* UDP数据接收队列 */
|
|||||||
|
|
||||||
void Air724_Message_Queue_Init(void)
|
void Air724_Message_Queue_Init(void)
|
||||||
{
|
{
|
||||||
Air724_Message_Queue = xQueueCreate(5, UART1_RX_BUFFER_SIZE);
|
Air724_Message_Queue = xQueueCreate(20, UART1_RX_BUFFER_SIZE);
|
||||||
if (Air724_Message_Queue == NULL)
|
if (Air724_Message_Queue == NULL)
|
||||||
{
|
{
|
||||||
printf("Air724_Message_Queue_Init Failed\r\n");
|
printf("Air724_Message_Queue_Init Failed\r\n");
|
||||||
@@ -43,7 +43,7 @@ void RS485_Message_Queue_Init(void)
|
|||||||
|
|
||||||
void UDP_Message_Queue_Init(void)
|
void UDP_Message_Queue_Init(void)
|
||||||
{
|
{
|
||||||
UDP_Message_Queue = xQueueCreate(5, sizeof(UdpMsg_t));
|
UDP_Message_Queue = xQueueCreate(20, sizeof(UdpMsg_t));
|
||||||
if (UDP_Message_Queue == NULL)
|
if (UDP_Message_Queue == NULL)
|
||||||
{
|
{
|
||||||
// 创建失败处理
|
// 创建失败处理
|
||||||
|
|||||||
@@ -12,26 +12,26 @@
|
|||||||
#include "os_task.h"
|
#include "os_task.h"
|
||||||
|
|
||||||
/*-任务句柄-*/
|
/*-任务句柄-*/
|
||||||
osThreadId HeartbeatTaskHandle; /* 心跳任务句柄 */
|
osThreadId SysTaskHandle; /* 系统任务句柄 */
|
||||||
|
|
||||||
osThreadId UDPTaskHandle; /* UDP 消息队列接受任务句柄 */
|
osThreadId UDPTaskHandle; /* UDP 消息队列接受任务句柄 */
|
||||||
|
|
||||||
osThreadId UDP_ParseTaskHandle; /* UDP 消息队列解析任务句柄 */
|
osThreadId UDP_ParseTaskHandle; /* UDP 消息队列解析任务句柄 */
|
||||||
|
|
||||||
osThreadId DownLinkTaskHandle; /* 4G接收消息任务句柄 */
|
osThreadId Air724_ParseTaskHandle; /* 4G消息队列解析任务句柄 */
|
||||||
|
|
||||||
osThreadId YkcTaskHandle; /* 云快充平台交互任务句柄 */
|
osThreadId YkcTaskHandle; /* 云快充平台交互任务句柄 */
|
||||||
|
|
||||||
/*-函数声明-*/
|
/*-函数声明-*/
|
||||||
void HeartbeatTask_Function(void const *argument); // 心跳任务
|
void sys_task_function(void const *argument); // 系统任务
|
||||||
|
|
||||||
void UDPTask_Function(void const *argument); // UDP 接受任务
|
void udp_recv_task_function(void const *argument); // UDP 接受任务
|
||||||
|
|
||||||
void UDP_ParseTask_Function(void const *argument); //UDP消息解析任务
|
void udp_parse_task_function(void const *argument); //UDP消息解析任务
|
||||||
|
|
||||||
void YkcTask_Function(void const *argument); // 云快充平台交互任务
|
void ykc_task_function(void const *argument); // 云快充平台交互主任务
|
||||||
|
|
||||||
void DownLinkTask_Function(void const *argument); // 4G接收消息任务
|
void air724_recv_task_function(void const *argument); // 云快充 TCP 消息解析任务
|
||||||
|
|
||||||
/* code -----------------------------------------------------------------------*/
|
/* code -----------------------------------------------------------------------*/
|
||||||
|
|
||||||
@@ -49,20 +49,16 @@ void Os_Task_Init(void) /*任务入口函数、任务名字、任务栈大小、
|
|||||||
{
|
{
|
||||||
BaseType_t xReturn = pdPASS;
|
BaseType_t xReturn = pdPASS;
|
||||||
|
|
||||||
/* 心跳任务 */
|
/* 系统任务 */
|
||||||
xReturn = xTaskCreate((TaskFunction_t)HeartbeatTask_Function, "HeartbeatTask", 128, NULL, (UBaseType_t)osPriorityLow, &HeartbeatTaskHandle);
|
xReturn = xTaskCreate((TaskFunction_t)sys_task_function, "SysTask", 128, NULL, (UBaseType_t)osPriorityLow, &SysTaskHandle);
|
||||||
|
/* 云快充 TCP 消息解析任务 */
|
||||||
/* 4G消息解析任务 */
|
xReturn = xTaskCreate((TaskFunction_t)air724_recv_task_function, "Air724RecvTask", 1024, NULL, osPriorityAboveNormal, &Air724_ParseTaskHandle);
|
||||||
xReturn = xTaskCreate((TaskFunction_t)DownLinkTask_Function, "DownLinkTask", 1024, NULL, osPriorityAboveNormal, &DownLinkTaskHandle);
|
|
||||||
|
|
||||||
/* UDP 消息队列接受任务 */
|
/* UDP 消息队列接受任务 */
|
||||||
xReturn = xTaskCreate((TaskFunction_t)UDPTask_Function, "UDPTask", 1536, NULL, osPriorityHigh, &UDPTaskHandle);
|
xReturn = xTaskCreate((TaskFunction_t)udp_recv_task_function, "UDPRecvTask", 1536, NULL, osPriorityHigh, &UDPTaskHandle);
|
||||||
|
|
||||||
/* UDP 消息解析任务 */
|
/* UDP 消息解析任务 */
|
||||||
xReturn = xTaskCreate((TaskFunction_t)UDP_ParseTask_Function, "UDPParseTask", 2048, NULL, osPriorityAboveNormal, &UDP_ParseTaskHandle);
|
xReturn = xTaskCreate((TaskFunction_t)udp_parse_task_function, "UDPParseTask", 2048, NULL, osPriorityAboveNormal, &UDP_ParseTaskHandle);
|
||||||
|
|
||||||
/* 云快充平台交互任务 */
|
/* 云快充平台交互任务 */
|
||||||
xReturn = xTaskCreate((TaskFunction_t)YkcTask_Function, "YKCTask", 1024, NULL, osPriorityAboveNormal, &YkcTaskHandle);
|
xReturn = xTaskCreate((TaskFunction_t)ykc_task_function, "YKC_Task", 1024, NULL, osPriorityAboveNormal, &YkcTaskHandle);
|
||||||
|
|
||||||
if (xReturn == pdPASS)
|
if (xReturn == pdPASS)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
void Os_Task_Init(void);
|
void Os_Task_Init(void);
|
||||||
|
|
||||||
/* Exported constants --------------------------------------------------------*/
|
/* Exported constants --------------------------------------------------------*/
|
||||||
extern osThreadId HeartbeatTaskHandle; /* 心跳任务句柄 */
|
extern osThreadId SysTaskHandle; /* 系统任务句柄 */
|
||||||
|
|
||||||
extern osThreadId UDPTaskHandle; /* UDP 消息队列接受任务句柄 */
|
extern osThreadId UDPTaskHandle; /* UDP 消息队列接受任务句柄 */
|
||||||
|
|
||||||
extern osThreadId UDP_ParseTaskHandle; /* UDP 消息队列解析任务句柄 */
|
extern osThreadId UDP_ParseTaskHandle; /* UDP 消息队列解析任务句柄 */
|
||||||
|
|
||||||
extern osThreadId DownLinkTaskHandle; /* 消息任务句柄 */
|
extern osThreadId Air724_ParseTaskHandle; /* 4G消息队列解析任务句柄 */
|
||||||
|
|
||||||
extern osThreadId YkcTaskHandle; /* 云快充平台交互任务句柄 */
|
extern osThreadId YkcTaskHandle; /* 云快充平台交互任务句柄 */
|
||||||
|
|
||||||
|
|||||||
147
Core/User/Os/os_timer.c
Normal file
147
Core/User/Os/os_timer.c
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file user\os\os_timer.c
|
||||||
|
* @author luhuaishuai
|
||||||
|
* @version v0.1
|
||||||
|
* @date 2026-1-12
|
||||||
|
* @brief 软件定时器管理
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Includes -------------------------------------------------------------------*/
|
||||||
|
#include "os_timer.h"
|
||||||
|
#include "task_ykc.h"
|
||||||
|
|
||||||
|
/* variables ------------------------------------------------------------------*/
|
||||||
|
TimerHandle_t YkcTimerHandle = NULL;
|
||||||
|
|
||||||
|
/* code -----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 软件定时器初始化
|
||||||
|
* @note 需要在 FreeRTOS 启动前调用
|
||||||
|
* @param none
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void SwTimer_Init(void)
|
||||||
|
{
|
||||||
|
SwTimer_YkcTimer_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建软件定时器
|
||||||
|
* @param name 定时器名称
|
||||||
|
* @param period_ms 定时周期(ms)
|
||||||
|
* @param auto_reload true:周期模式 false:单次模式
|
||||||
|
* @param callback 定时器回调函数
|
||||||
|
* @retval TimerHandle_t 定时器句柄,NULL 表示创建失败
|
||||||
|
*/
|
||||||
|
TimerHandle_t SwTimer_Create(const char *name,
|
||||||
|
uint32_t period_ms,
|
||||||
|
bool auto_reload,
|
||||||
|
SwTimerCallback_t callback)
|
||||||
|
{
|
||||||
|
UBaseType_t reload = auto_reload ? pdTRUE : pdFALSE;
|
||||||
|
TimerHandle_t xTimer = xTimerCreate(name,
|
||||||
|
pdMS_TO_TICKS(period_ms),
|
||||||
|
reload,
|
||||||
|
NULL,
|
||||||
|
callback);
|
||||||
|
|
||||||
|
if (xTimer == NULL)
|
||||||
|
{
|
||||||
|
printf("SwTimer_Create Failed: %s\r\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 启动软件定时器
|
||||||
|
* @param xTimer 定时器句柄
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void SwTimer_Start(TimerHandle_t xTimer)
|
||||||
|
{
|
||||||
|
if (xTimer != NULL)
|
||||||
|
{
|
||||||
|
if (xTimerStart(xTimer, 0) != pdPASS)
|
||||||
|
{
|
||||||
|
printf("SwTimer_Start Failed\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 停止软件定时器
|
||||||
|
* @param xTimer 定时器句柄
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void SwTimer_Stop(TimerHandle_t xTimer)
|
||||||
|
{
|
||||||
|
if (xTimer != NULL)
|
||||||
|
{
|
||||||
|
if (xTimerStop(xTimer, 0) != pdPASS)
|
||||||
|
{
|
||||||
|
printf("SwTimer_Stop Failed\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 复位软件定时器
|
||||||
|
* @param xTimer 定时器句柄
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void SwTimer_Reset(TimerHandle_t xTimer)
|
||||||
|
{
|
||||||
|
if (xTimer != NULL)
|
||||||
|
{
|
||||||
|
if (xTimerReset(xTimer, 0) != pdPASS)
|
||||||
|
{
|
||||||
|
printf("SwTimer_Reset Failed\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建充电桩状态检查定时器
|
||||||
|
* @note 500ms 周期,自动重载,遍历检查 1-6 号桩状态
|
||||||
|
* @param none
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void SwTimer_YkcTimer_Init(void)
|
||||||
|
{
|
||||||
|
YkcTimerHandle = SwTimer_Create("YkcTimer",
|
||||||
|
2500,
|
||||||
|
true,
|
||||||
|
ykc_timer_callback_function);
|
||||||
|
|
||||||
|
if (YkcTimerHandle != NULL)
|
||||||
|
{
|
||||||
|
SwTimer_Start(YkcTimerHandle);
|
||||||
|
printf("YkcTimer_Init\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("YkcTimer_Init Failed\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 修改定时器周期
|
||||||
|
* @param xTimer 定时器句柄
|
||||||
|
* @param period_ms 新周期(ms)
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void SwTimer_ChangePeriod(TimerHandle_t xTimer, uint32_t period_ms)
|
||||||
|
{
|
||||||
|
if (xTimer != NULL)
|
||||||
|
{
|
||||||
|
if (xTimerChangePeriod(xTimer, pdMS_TO_TICKS(period_ms), 0) != pdPASS)
|
||||||
|
{
|
||||||
|
printf("SwTimer_ChangePeriod Failed\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Core/User/Os/os_timer.h
Normal file
29
Core/User/Os/os_timer.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef __OSTIMER_H
|
||||||
|
#define __OSTIMER_H
|
||||||
|
|
||||||
|
/* Private includes ----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
/* Exported types ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
typedef void (*SwTimerCallback_t)(TimerHandle_t xTimer);
|
||||||
|
|
||||||
|
/* Exported functions prototypes ---------------------------------------------*/
|
||||||
|
|
||||||
|
void SwTimer_Init(void);
|
||||||
|
TimerHandle_t SwTimer_Create(const char *name,
|
||||||
|
uint32_t period_ms,
|
||||||
|
bool auto_reload,
|
||||||
|
SwTimerCallback_t callback);
|
||||||
|
void SwTimer_Start(TimerHandle_t xTimer);
|
||||||
|
void SwTimer_Stop(TimerHandle_t xTimer);
|
||||||
|
void SwTimer_Reset(TimerHandle_t xTimer);
|
||||||
|
|
||||||
|
void SwTimer_ChangePeriod(TimerHandle_t xTimer, uint32_t period_ms);
|
||||||
|
void SwTimer_YkcTimer_Init(void);
|
||||||
|
|
||||||
|
/* Exported constants --------------------------------------------------------*/
|
||||||
|
extern TimerHandle_t YkcTimerHandle;
|
||||||
|
|
||||||
|
#endif
|
||||||
279
Core/User/Protocol/Host Computer/host_computer_protocol.c
Normal file
279
Core/User/Protocol/Host Computer/host_computer_protocol.c
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
/**
|
||||||
|
* @file host_computer_protocol.c
|
||||||
|
* @brief 上位机通信协议处理模块
|
||||||
|
* @details 处理上位机与充电桩之间的通信协议,包括登录验证、状态查询、
|
||||||
|
* 数据上报等功能。支持JSON格式的数据交互,通过UDP协议与服务器通信。
|
||||||
|
* @date 2025-01-09 14:32:15
|
||||||
|
* @version 1.0.0
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "host_computer_protocol.h"
|
||||||
|
#include "point_protocol.h"
|
||||||
|
|
||||||
|
void host_computer_on_login(uint8_t id, cJSON *json_pack)
|
||||||
|
{
|
||||||
|
(void) id;
|
||||||
|
cJSON *request_id = cJSON_GetObjectItem(json_pack, "request_id");
|
||||||
|
cJSON *username = cJSON_GetObjectItem(json_pack, "username");
|
||||||
|
cJSON *password = cJSON_GetObjectItem(json_pack, "password");
|
||||||
|
|
||||||
|
cJSON *root = NULL;
|
||||||
|
char *str = NULL;
|
||||||
|
|
||||||
|
root = cJSON_CreateObject();
|
||||||
|
if (root == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to create JSON object for server login\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
|
||||||
|
cJSON_AddStringToObject(root, "request_id", request_id->valuestring);
|
||||||
|
|
||||||
|
if (strcmp(username->valuestring, "admin") != 0 || strcmp(password->valuestring, "123456") != 0)
|
||||||
|
{
|
||||||
|
cJSON_AddStringToObject(root, "error", "用户或密码错误 ");
|
||||||
|
cJSON_AddBoolToObject(root, "success", cJSON_False);
|
||||||
|
printf("登录失败\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cJSON_AddBoolToObject(root, "success", cJSON_True);
|
||||||
|
printf("登录成功\r\n");
|
||||||
|
}
|
||||||
|
str = cJSON_Print(root);
|
||||||
|
udp_send_to_server(str, strlen(str));
|
||||||
|
free(str);
|
||||||
|
cJSON_Delete(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理获取状态查询指令
|
||||||
|
void host_computer_on_get_status(uint8_t id, cJSON *json_pack)
|
||||||
|
{
|
||||||
|
(void) id;
|
||||||
|
cJSON *request_id = cJSON_GetObjectItem(json_pack, "request_id");
|
||||||
|
|
||||||
|
cJSON *root = NULL;
|
||||||
|
cJSON *piles = NULL;
|
||||||
|
cJSON *pile = NULL;
|
||||||
|
cJSON *guns = NULL;
|
||||||
|
cJSON *gun = NULL;
|
||||||
|
char *str = NULL;
|
||||||
|
|
||||||
|
root = cJSON_CreateObject();
|
||||||
|
if (root == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to create JSON object for get_status\r");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_AddStringToObject(root, "request_id", request_id->valuestring);
|
||||||
|
cJSON_AddBoolToObject(root, "success", cJSON_True);
|
||||||
|
|
||||||
|
/* ── piles 数组 ── */
|
||||||
|
piles = cJSON_CreateArray();
|
||||||
|
|
||||||
|
/* 根据MAX_CHARGER_COUNT动态生成桩数据 */
|
||||||
|
for (int i = 0; i < MAX_CHARGER_COUNT; i++)
|
||||||
|
{
|
||||||
|
ChargerPile *pile_data = &g_charger_manager.charger_piles[i];
|
||||||
|
|
||||||
|
pile = cJSON_CreateObject();
|
||||||
|
if (pile == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 添加桩序列号 */
|
||||||
|
char serial_str[15] = {0};
|
||||||
|
for (int j = 0; j < 7; j++)
|
||||||
|
{
|
||||||
|
sprintf(&serial_str[j * 2], "%02X", pile_data->login_info.charger_serial[j]);
|
||||||
|
}
|
||||||
|
cJSON_AddStringToObject(pile, "serial", serial_str);
|
||||||
|
|
||||||
|
/* 添加在线状态 */
|
||||||
|
cJSON_AddBoolToObject(pile, "is_online", pile_data->is_udp_online ? cJSON_True : cJSON_False);
|
||||||
|
|
||||||
|
/* 创建guns数组 */
|
||||||
|
guns = cJSON_CreateArray();
|
||||||
|
if (guns != NULL)
|
||||||
|
{
|
||||||
|
for (int g = 0; g < MAX_GUN_PER_CHARGER; g++)
|
||||||
|
{
|
||||||
|
gun = cJSON_CreateObject();
|
||||||
|
if (gun != NULL)
|
||||||
|
{
|
||||||
|
/* 添加枪状态 */
|
||||||
|
cJSON_AddNumberToObject(gun, "status", pile_data->guns[g].real_time_data.status);
|
||||||
|
cJSON_AddItemToArray(guns, gun);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cJSON_AddItemToObject(pile, "guns", guns);
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_AddItemToArray(piles, pile);
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_AddItemToObject(root, "piles", piles);
|
||||||
|
|
||||||
|
/* ── 发送 ── */
|
||||||
|
str = cJSON_Print(root);
|
||||||
|
udp_send_to_server(str, strlen(str));
|
||||||
|
free(str);
|
||||||
|
cJSON_Delete(root);
|
||||||
|
printf("get_status 回复已发送 \r\n");
|
||||||
|
}
|
||||||
|
void host_computer_on_reboot(uint8_t id, cJSON *json)
|
||||||
|
{
|
||||||
|
(void) id;
|
||||||
|
printf("host_computer_on_reboot\r\n");
|
||||||
|
__ASM volatile("cpsid i");
|
||||||
|
HAL_NVIC_SystemReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 主动上报充电桩数据
|
||||||
|
* @note 模拟并上报充电桩实时数据,符合协议格式要求
|
||||||
|
* @param stake_index 桩索引 (1~6)
|
||||||
|
* @param gun_id 枪编码 (1~N)
|
||||||
|
*/
|
||||||
|
void host_computer_report_data(uint8_t stake_index, uint8_t gun_id)
|
||||||
|
{
|
||||||
|
if (stake_index > MAX_CHARGER_COUNT || stake_index == 0)
|
||||||
|
{
|
||||||
|
printf("Invalid stake index: %d\r\n", stake_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gun_id == 0 || gun_id > MAX_GUN_PER_CHARGER)
|
||||||
|
{
|
||||||
|
printf("Invalid gun id: %d\r\n", gun_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON *root = NULL;
|
||||||
|
cJSON *piles_array = NULL;
|
||||||
|
cJSON *pile_obj = NULL;
|
||||||
|
cJSON *guns_array = NULL;
|
||||||
|
cJSON *gun_obj = NULL;
|
||||||
|
char *str = NULL;
|
||||||
|
|
||||||
|
root = cJSON_CreateObject();
|
||||||
|
if (root == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to create JSON object for report_data\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 添加命令字段 */
|
||||||
|
cJSON_AddStringToObject(root, "cmd", "report_data");
|
||||||
|
|
||||||
|
/* 创建piles数组 */
|
||||||
|
piles_array = cJSON_CreateArray();
|
||||||
|
if (piles_array == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to create piles array\r\n");
|
||||||
|
cJSON_Delete(root);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 创建桩数据对象 */
|
||||||
|
pile_obj = cJSON_CreateObject();
|
||||||
|
if (pile_obj == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to create pile object\r\n");
|
||||||
|
cJSON_Delete(root);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 从结构体获取真实数据 */
|
||||||
|
ChargerGun *gun = &g_charger_manager.charger_piles[stake_index - 1].guns[gun_id - 1];
|
||||||
|
FEE_MODEL *model = &g_charger_manager.fee_model_global;
|
||||||
|
|
||||||
|
/* 存入结构体前放大过10倍,发送时缩小回去 */
|
||||||
|
float current = gun->real_time_data.out_current / 10.0f;
|
||||||
|
float voltage = gun->real_time_data.out_voltage / 10.0f;
|
||||||
|
float power = (voltage * current) / 1000.0f;
|
||||||
|
|
||||||
|
/* 电量(0.01kWh/单位) 金额(0.01元/单位) */
|
||||||
|
float energy = gun->real_time_data.charge_energy / 10000.0f;
|
||||||
|
float total_amount = gun->real_time_data.charge_money / 10000.0f;
|
||||||
|
|
||||||
|
/* 根据计费模型拆分电费/服务费 */
|
||||||
|
uint32_t fee_ratio_sum = model->flat_fee_ratio + model->flat_service_ratio;
|
||||||
|
float electricity_fee = (fee_ratio_sum > 0) ? total_amount * model->flat_fee_ratio / fee_ratio_sum : 0;
|
||||||
|
float service_fee = total_amount - electricity_fee;
|
||||||
|
|
||||||
|
int status = gun->real_time_data.status;
|
||||||
|
int cumulative_time = gun->real_time_data.charge_time;
|
||||||
|
int remaining_time = gun->real_time_data.remain_time;
|
||||||
|
uint8_t soc = gun->real_time_data.soc;
|
||||||
|
|
||||||
|
/* 交易流水号 → 十六进制字符串 */
|
||||||
|
char order_no[33] = {0};
|
||||||
|
trade_serial_to_string(gun->real_time_data.trade_serial, order_no);
|
||||||
|
|
||||||
|
/* 模拟桩数据 */
|
||||||
|
cJSON_AddNumberToObject(pile_obj, "index", stake_index);
|
||||||
|
|
||||||
|
/* 创建guns数组 */
|
||||||
|
guns_array = cJSON_CreateArray();
|
||||||
|
if (guns_array == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to create guns array\r\n");
|
||||||
|
cJSON_Delete(pile_obj);
|
||||||
|
cJSON_Delete(root);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 创建枪数据对象 */
|
||||||
|
gun_obj = cJSON_CreateObject();
|
||||||
|
if (gun_obj == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to create gun object\r\n");
|
||||||
|
cJSON_Delete(guns_array);
|
||||||
|
cJSON_Delete(pile_obj);
|
||||||
|
cJSON_Delete(root);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 枪数据 */
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "gun", gun_id);
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "current", current); // 电流(随机变化)
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "voltage", voltage); // 电压(随机变化)
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "power", power); // 功率(随机变化)
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "energy", energy); // 电量(随机变化)
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "service_fee", service_fee); // 服务费(随机变化)
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "electricity_fee", electricity_fee); // 电费(随机变化)
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "total_amount", total_amount); // 总金额(随机变化)
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "status", status); // 状态
|
||||||
|
cJSON_AddStringToObject(gun_obj, "order_no", order_no);
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "soc", soc); // SOC(随机变化)
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "cumulative_time", cumulative_time); // 累计充电时间(随机变化)
|
||||||
|
cJSON_AddNumberToObject(gun_obj, "remaining_time", remaining_time); // 剩余时间(随机变化)
|
||||||
|
|
||||||
|
cJSON_AddItemToArray(guns_array, gun_obj);
|
||||||
|
cJSON_AddItemToObject(pile_obj, "guns", guns_array);
|
||||||
|
|
||||||
|
cJSON_AddItemToArray(piles_array, pile_obj);
|
||||||
|
cJSON_AddItemToObject(root, "piles", piles_array);
|
||||||
|
|
||||||
|
/* 转换为JSON字符串并发送 */
|
||||||
|
str = cJSON_Print(root);
|
||||||
|
if (str != NULL)
|
||||||
|
{
|
||||||
|
udp_send_to_server(str, strlen(str));
|
||||||
|
free(str);
|
||||||
|
printf("南向:主动上报桩 %d 枪 %d 主动上报数据成功 \r\n", stake_index, gun_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Failed to print JSON for report_data\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_Delete(root);
|
||||||
|
}
|
||||||
|
|
||||||
16
Core/User/Protocol/Host Computer/host_computer_protocol.h
Normal file
16
Core/User/Protocol/Host Computer/host_computer_protocol.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef HOST_COMPUTER_HANDLER_H
|
||||||
|
#define HOST_COMPUTER_HANDLER_H
|
||||||
|
#include "global.h"
|
||||||
|
#include "cJSON.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "udp_manager.h"
|
||||||
|
|
||||||
|
/* ── 路由表注册接口(供 UdpRouter 调用)─────────────── */
|
||||||
|
void host_computer_on_login (uint8_t id, cJSON *json);
|
||||||
|
void host_computer_on_get_status(uint8_t id, cJSON *json);
|
||||||
|
void host_computer_on_reboot (uint8_t id, cJSON *json);
|
||||||
|
|
||||||
|
/* ── 主动上报接口(供业务层调用)────────────────────── */
|
||||||
|
void host_computer_report_data(uint8_t stake_index, uint8_t gun_id);
|
||||||
|
|
||||||
|
#endif /* HOST_COMPUTER_HANDLER_H */
|
||||||
1074
Core/User/Protocol/Point/point_protocol.c
Normal file
1074
Core/User/Protocol/Point/point_protocol.c
Normal file
File diff suppressed because it is too large
Load Diff
27
Core/User/Protocol/Point/point_protocol.h
Normal file
27
Core/User/Protocol/Point/point_protocol.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef POINT_HANDLER_H
|
||||||
|
#define POINT_HANDLER_H
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
#include "cJSON.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "udp_manager.h"
|
||||||
|
|
||||||
|
/* ── 路由表注册接口─────────────── */
|
||||||
|
void point_callback_power_on(uint8_t id, cJSON *json); // 上电
|
||||||
|
void point_callback_heartbeat(uint8_t id, cJSON *json); // 心跳包
|
||||||
|
void point_callback_start_charging(uint8_t stake_index, cJSON *json_pack); // 开始充电反馈
|
||||||
|
void point_callback_end_charging(uint8_t stake_index, cJSON *json_pack); // 停止充电反馈
|
||||||
|
void point_callback_realtime_data(uint8_t stake_index, cJSON *json); // 实时数据
|
||||||
|
void point_callback_settlement_bill(uint8_t stake_index, cJSON *json); // 结算单
|
||||||
|
void point_callback_proactive_end(uint8_t stake_index, cJSON *json); // 主动结束
|
||||||
|
void point_callback_charge_process(uint8_t stake_index, cJSON *json); // 实时信息
|
||||||
|
void point_callback_bms_info(uint8_t stake_index, cJSON *json); // BMS 信息
|
||||||
|
void point_callback_proactive_end_charging(uint8_t stake_index, cJSON *json_pack); // 主动结束充电
|
||||||
|
/* ── 主动下发接口(供业务层调用)────────────────────── */
|
||||||
|
void point_send_start_charging(uint8_t stake_index, uint8_t gun_id); // 开始充电
|
||||||
|
void point_send_stop_charging(uint8_t stake_index, uint8_t gun_id); // 停止充电
|
||||||
|
|
||||||
|
/* ── 工具函数 ─────────────────────────────────────────── */
|
||||||
|
void trade_serial_to_string(uint8_t *trade_serial, char *output_str); // 转换交易序列号为字符串
|
||||||
|
|
||||||
|
#endif /* POINT_HANDLER_H */
|
||||||
@@ -1,3 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* @file charger_to_server.c
|
||||||
|
* @brief 充电桩通信协议处理模块 上行数据
|
||||||
|
* @details 处理充电桩与服务器之间的通信协议,包括登录验证、心跳请求、计费模型验证请求、
|
||||||
|
* 数据上报等功能。支持字节码格式的数据交互,通过串口协议与服务器通信。
|
||||||
|
* @date 2025-01-09 14:32:15
|
||||||
|
* @version 1.0.0
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*/
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "charger_to_server.h"
|
#include "charger_to_server.h"
|
||||||
|
|
||||||
@@ -7,6 +16,8 @@ uint16_t pack_serial = 0;
|
|||||||
void charger_to_server_0X01(uint8_t stake_index)
|
void charger_to_server_0X01(uint8_t stake_index)
|
||||||
{
|
{
|
||||||
PACK_DATA_0X01 data = {0};
|
PACK_DATA_0X01 data = {0};
|
||||||
|
ChargerPile *point = &g_charger_manager.charger_piles[stake_index - 1];
|
||||||
|
|
||||||
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
|
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
|
||||||
data.charger_type = g_charger_manager.charger_piles[stake_index - 1].login_info.charger_type;
|
data.charger_type = g_charger_manager.charger_piles[stake_index - 1].login_info.charger_type;
|
||||||
data.gun_num = g_charger_manager.charger_piles[stake_index - 1].login_info.gun_num;
|
data.gun_num = g_charger_manager.charger_piles[stake_index - 1].login_info.gun_num;
|
||||||
@@ -19,14 +30,14 @@ void charger_to_server_0X01(uint8_t stake_index)
|
|||||||
pack_and_send_server_data(FRAME_TYPE_0X01, (uint8_t *)&data, sizeof(PACK_DATA_0X01), stake_index);
|
pack_and_send_server_data(FRAME_TYPE_0X01, (uint8_t *)&data, sizeof(PACK_DATA_0X01), stake_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void charger_to_server_0X03(uint8_t stake_index, uint8_t gun_index, uint8_t gun_status)
|
void charger_to_server_0X03(uint8_t stake_index, uint8_t gun_index)
|
||||||
{
|
{
|
||||||
PACK_DATA_0X03 data = {0};
|
PACK_DATA_0X03 data = {0};
|
||||||
|
|
||||||
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
|
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
|
||||||
data.gun_index = gun_index;
|
data.gun_index = ((gun_index / 10) << 4) | (gun_index % 10);
|
||||||
data.gun_status = gun_status;
|
data.gun_status = g_charger_manager.charger_piles[stake_index - 1].guns[gun_index - 1].heartbeat_status_data.gun_status;
|
||||||
printf("北向:对电桩 %d 发送心跳请求,枪号:%d,状态:%d\r\n", stake_index, gun_index, gun_status);
|
printf("北向:对电桩 %d 发送心跳请求,枪号:%d,状态:%d\r\n", stake_index, gun_index, data.gun_status);
|
||||||
pack_and_send_server_data(FRAME_TYPE_0X03, (uint8_t *)&data, sizeof(PACK_DATA_0X03), stake_index);
|
pack_and_send_server_data(FRAME_TYPE_0X03, (uint8_t *)&data, sizeof(PACK_DATA_0X03), stake_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +56,6 @@ void charger_to_server_0X05(uint16_t num, uint8_t stake_index)
|
|||||||
void charger_to_server_0X09(uint8_t stake_index)
|
void charger_to_server_0X09(uint8_t stake_index)
|
||||||
{
|
{
|
||||||
PACK_DATA_0X09 data = {0};
|
PACK_DATA_0X09 data = {0};
|
||||||
|
|
||||||
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
|
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
|
||||||
printf("北向:对电桩 %d 计费模型请求,序列号:%s\r\n", stake_index, data.charger_serial);
|
printf("北向:对电桩 %d 计费模型请求,序列号:%s\r\n", stake_index, data.charger_serial);
|
||||||
pack_and_send_server_data(FRAME_TYPE_0X09, (uint8_t *)&data, sizeof(PACK_DATA_0X09), stake_index);
|
pack_and_send_server_data(FRAME_TYPE_0X09, (uint8_t *)&data, sizeof(PACK_DATA_0X09), stake_index);
|
||||||
@@ -60,7 +70,7 @@ void charger_to_server_0X13(uint8_t stake_index, uint8_t gun_index)
|
|||||||
// 覆盖需要重新加载的字段
|
// 覆盖需要重新加载的字段
|
||||||
load_charger_serial(stake_index, data.charger_serial);
|
load_charger_serial(stake_index, data.charger_serial);
|
||||||
load_trade_serial(stake_index, gun_index, data.trade_serial);
|
load_trade_serial(stake_index, gun_index, data.trade_serial);
|
||||||
data.gun_index = gun_index;
|
data.gun_index = ((gun_index / 10) << 4) | (gun_index % 10);
|
||||||
|
|
||||||
// 根据状态清零特定字段
|
// 根据状态清零特定字段
|
||||||
if (data.status == 0x01 || data.status == 0x02 || data.status == 0x00)
|
if (data.status == 0x01 || data.status == 0x02 || data.status == 0x00)
|
||||||
@@ -92,20 +102,12 @@ void charger_to_server_0X33(uint8_t stake_index, uint8_t gun_index, uint8_t resu
|
|||||||
PACK_DATA_0X33 data = {0};
|
PACK_DATA_0X33 data = {0};
|
||||||
load_charger_serial(stake_index, data.charger_serial);
|
load_charger_serial(stake_index, data.charger_serial);
|
||||||
load_trade_serial(stake_index, gun_index, data.trade_serial);
|
load_trade_serial(stake_index, gun_index, data.trade_serial);
|
||||||
data.gun_index = gun_index;
|
data.gun_index = ((gun_index / 10) << 4) | (gun_index % 10);
|
||||||
|
|
||||||
data.result = result;
|
data.result = result;
|
||||||
data.err_code = err_code;
|
data.err_code = err_code;
|
||||||
|
|
||||||
uint8_t *trade_serial = g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.trade_serial;
|
printf(" └── 网关向云快充发送 [%s] 电桩 %d 枪 %d的平台启动回复,结果:%d,错误码:%d\r\n",result == 0 ? "error" : "success", stake_index, gun_index, result, err_code);
|
||||||
|
|
||||||
printf("回复订单ID: ");
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
printf("%02X", trade_serial[i]);
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
|
|
||||||
printf("北向:对电桩 %d 的平台启动回复,结果:%d,错误码:%d\r\n", stake_index, result, err_code);
|
|
||||||
pack_and_send_server_data(FRAME_TYPE_0X33, (uint8_t *)&data, sizeof(PACK_DATA_0X33), stake_index);
|
pack_and_send_server_data(FRAME_TYPE_0X33, (uint8_t *)&data, sizeof(PACK_DATA_0X33), stake_index);
|
||||||
}
|
}
|
||||||
// 平台停机回复
|
// 平台停机回复
|
||||||
@@ -113,7 +115,7 @@ void charger_to_server_0X35(uint8_t stake_index, uint8_t gun_index, uint8_t resu
|
|||||||
{
|
{
|
||||||
PACK_DATA_0X35 data = {0};
|
PACK_DATA_0X35 data = {0};
|
||||||
load_charger_serial(stake_index, data.charger_serial);
|
load_charger_serial(stake_index, data.charger_serial);
|
||||||
data.gun_index = gun_index;
|
data.gun_index = ((gun_index / 10) << 4) | (gun_index % 10);
|
||||||
data.result = result;
|
data.result = result;
|
||||||
data.err_code = err_code;
|
data.err_code = err_code;
|
||||||
|
|
||||||
@@ -121,18 +123,55 @@ void charger_to_server_0X35(uint8_t stake_index, uint8_t gun_index, uint8_t resu
|
|||||||
pack_and_send_server_data(FRAME_TYPE_0X35, (uint8_t *)&data, sizeof(PACK_DATA_0X35), stake_index);
|
pack_and_send_server_data(FRAME_TYPE_0X35, (uint8_t *)&data, sizeof(PACK_DATA_0X35), stake_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 上传交易记录
|
// 上传交易记录
|
||||||
void charger_to_server_0X3B(uint8_t stake_index, uint8_t gun_index)
|
void charger_to_server_0X3B(uint8_t stake_index, uint8_t gun_index)
|
||||||
{
|
{
|
||||||
PACK_DATA_0X3B data = {0};
|
PACK_DATA_0X3B data = {0};
|
||||||
load_charger_serial(stake_index, data.charger_serial);
|
ChargerGun *gun = &g_charger_manager.charger_piles[stake_index - 1].guns[gun_index - 1];
|
||||||
load_trade_serial(stake_index, gun_index, data.trade_serial);
|
|
||||||
data.gun_index = gun_index;
|
|
||||||
|
|
||||||
|
load_charger_serial(stake_index, data.charger_serial); // 加载电桩编号
|
||||||
|
load_trade_serial(stake_index, gun_index, data.trade_serial); // 加载交易记录
|
||||||
|
data.gun_index = ((gun_index / 10) << 4) | (gun_index % 10); // 枪索引
|
||||||
|
memcpy(data.start_time, gun->fee_data.start_time, 7); // 充电开始时间戳
|
||||||
|
memcpy(data.end_time, gun->fee_data.end_time, 7); // 充电结束时间戳
|
||||||
|
|
||||||
|
data.shark_price = gun->fee_data.shark_price; // 尖单价
|
||||||
|
data.shark_energy = gun->fee_data.shark_energy; // 尖电量
|
||||||
|
data.loss_shark_energy = gun->fee_data.loss_shark_energy; // 尖损失电量
|
||||||
|
data.shark_money = gun->fee_data.shark_money; // 尖金额
|
||||||
|
|
||||||
|
data.peak_price = gun->fee_data.peak_price; // 峰单价
|
||||||
|
data.peak_energy = gun->fee_data.peak_energy; // 峰电量
|
||||||
|
data.loss_peak_energy = gun->fee_data.loss_peak_energy; // 峰损失电量
|
||||||
|
data.peak_money = gun->fee_data.peak_money; // 峰金额
|
||||||
|
|
||||||
|
data.flat_price = gun->fee_data.flat_price; // 平单价
|
||||||
|
data.flat_energy = gun->fee_data.flat_energy; // 平电量
|
||||||
|
data.loss_flat_energy = gun->fee_data.loss_flat_energy; // 平损失电量
|
||||||
|
data.flat_money = gun->fee_data.flat_money; // 平金额
|
||||||
|
|
||||||
|
data.valley_price = gun->fee_data.valley_price; // 谷单价
|
||||||
|
data.valley_energy = gun->fee_data.valley_energy; // 谷电量
|
||||||
|
data.loss_valley_energy = gun->fee_data.loss_valley_energy; // 谷损失电量
|
||||||
|
data.valley_money = gun->fee_data.valley_money; // 谷金额
|
||||||
|
|
||||||
|
memcpy(data.meter_start_value, gun->fee_data.meter_start_value, 4); // 电表充电开始值
|
||||||
|
memcpy(data.meter_end_value, gun->fee_data.meter_end_value, 4); // 电表充电结束值
|
||||||
|
|
||||||
|
data.total_energy = gun->fee_data.total_energy; // 充电电量
|
||||||
|
data.loss_total_energy = gun->fee_data.loss_total_energy; // 损失电量
|
||||||
|
data.consumption = gun->fee_data.consumption; // 金额
|
||||||
|
|
||||||
|
data.trade_flag = 0x01;
|
||||||
|
data.stop_reason = gun->fee_data.stop_reason; // 停机原因
|
||||||
|
memcpy(data.trade_time, gun->fee_data.trade_time, 7); // 交易时间
|
||||||
|
memcpy(data.vin, gun->fee_data.vin, 17); // VIN码
|
||||||
|
memcpy(data.phy_cardid, gun->fee_data.phy_cardid, 8); // 物理卡号
|
||||||
|
|
||||||
|
printf("========================================\r\n");
|
||||||
|
printf("北向:对电桩 %d 枪 %d 上传交易记录(0x3B),电量:%.2f,金额:%.2f\r\n",
|
||||||
|
stake_index, gun_index, data.total_energy / 10000.0f, data.consumption / 10000.0f);
|
||||||
|
printf("\r\n========================================\r\n");
|
||||||
pack_and_send_server_data(FRAME_TYPE_0X3B, (uint8_t *)&data, sizeof(PACK_DATA_0X3B), stake_index);
|
pack_and_send_server_data(FRAME_TYPE_0X3B, (uint8_t *)&data, sizeof(PACK_DATA_0X3B), stake_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ uint32_t get_current_rtc_sec();
|
|||||||
extern void charger_to_server_0X01(uint8_t stake_index);
|
extern void charger_to_server_0X01(uint8_t stake_index);
|
||||||
|
|
||||||
//充电桩心跳包
|
//充电桩心跳包
|
||||||
extern void charger_to_server_0X03(uint8_t stake_index,uint8_t gun_index,uint8_t gun_status);
|
extern void charger_to_server_0X03(uint8_t stake_index,uint8_t gun_index);
|
||||||
|
|
||||||
//计费模型验证请求
|
//计费模型验证请求
|
||||||
extern void charger_to_server_0X05(uint16_t num,uint8_t stake_index);
|
extern void charger_to_server_0X05(uint16_t num,uint8_t stake_index);
|
||||||
@@ -30,7 +30,7 @@ extern void charger_to_server_0X19(uint8_t stake_index,uint8_t gun_index);
|
|||||||
extern void charger_to_server_0X33(uint8_t stake_index,uint8_t gun_index, uint8_t result, uint8_t err_code);
|
extern void charger_to_server_0X33(uint8_t stake_index,uint8_t gun_index, uint8_t result, uint8_t err_code);
|
||||||
extern void charger_to_server_0X35(uint8_t stake_index, uint8_t gun_index, uint8_t result, uint8_t err_code);
|
extern void charger_to_server_0X35(uint8_t stake_index, uint8_t gun_index, uint8_t result, uint8_t err_code);
|
||||||
|
|
||||||
extern void charger_to_server_0x3B(uint8_t gun_index,uint32_t card_id,uint8_t trade_flag,uint8_t stop_reason); //3B¸ÄΪ3D
|
extern void charger_to_server_0X3B(uint8_t stake_index, uint8_t gun_index);
|
||||||
|
|
||||||
//余额更新应答
|
//余额更新应答
|
||||||
void charger_to_server_0X41(uint8_t * card_id, uint8_t result) ;
|
void charger_to_server_0X41(uint8_t * card_id, uint8_t result) ;
|
||||||
@@ -38,7 +38,6 @@ extern void charger_to_server_0x3B(uint8_t gun_index,uint32_t card_id,uint8_t tr
|
|||||||
//对时设置应答
|
//对时设置应答
|
||||||
extern void charger_to_server_0X55(uint32_t time);
|
extern void charger_to_server_0X55(uint32_t time);
|
||||||
|
|
||||||
|
|
||||||
//计费模型应答
|
//计费模型应答
|
||||||
extern void charger_to_server_0X57(uint8_t stake_index);
|
extern void charger_to_server_0X57(uint8_t stake_index);
|
||||||
extern uint8_t get_real_status_for_server(uint8_t idx);
|
extern uint8_t get_real_status_for_server(uint8_t idx);
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
uint8_t trade_serial[2][TRADE_SERIAL_LENGTH] = {0};
|
uint8_t trade_serial[2][TRADE_SERIAL_LENGTH] = {0};
|
||||||
static FEE_MODEL current_setting_fee_model = {0};
|
static FEE_MODEL current_setting_fee_model = {0};
|
||||||
|
|
||||||
@@ -55,40 +54,37 @@ uint32_t get_card_logic_num(uint8_t idx)
|
|||||||
|
|
||||||
void load_charger_serial(uint8_t stake_mark, uint8_t *serial)
|
void load_charger_serial(uint8_t stake_mark, uint8_t *serial)
|
||||||
{
|
{
|
||||||
// memcpy(serial, charger_serial[stake_mark - 1], CHARGER_SERIAL_LENGTH);
|
if (stake_mark > MAX_CHARGER_COUNT)
|
||||||
memcpy(serial, g_charger_manager.charger_piles[stake_mark - 1].login_info.charger_serial, CHARGER_SERIAL_LENGTH);
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(serial, g_charger_manager.charger_piles[stake_mark - 1].charger_serial, CHARGER_SERIAL_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void set_charger_serial_for_server(uint8_t value, uint8_t offset)
|
|
||||||
// {
|
|
||||||
// uint8_t hi = 0;
|
|
||||||
// uint8_t lo = 0;
|
|
||||||
// if (offset >= CHARGER_SERIAL_LENGTH)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// hi = value / 10;
|
|
||||||
// lo = value % 10;
|
|
||||||
// charger_serial[offset] = hi * 16 + lo;
|
|
||||||
// }
|
|
||||||
|
|
||||||
void set_trade_serial(uint8_t stake_mark, uint8_t idx, uint8_t *serial)
|
void set_trade_serial(uint8_t stake_mark, uint8_t idx, uint8_t *serial)
|
||||||
{
|
{
|
||||||
idx = idx - 1;
|
if (stake_mark > MAX_CHARGER_COUNT)
|
||||||
if (idx < 2)
|
|
||||||
{
|
{
|
||||||
memcpy(g_charger_manager.charger_piles[stake_mark - 1].guns[idx].real_time_data.trade_serial, serial, TRADE_SERIAL_LENGTH);
|
return;
|
||||||
}
|
}
|
||||||
|
if (idx > MAX_GUN_PER_CHARGER)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(g_charger_manager.charger_piles[stake_mark - 1].guns[idx - 1].real_time_data.trade_serial, serial, TRADE_SERIAL_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_trade_serial(uint8_t stake_mark, uint8_t idx, uint8_t *serial)
|
void load_trade_serial(uint8_t stake_mark, uint8_t idx, uint8_t *serial)
|
||||||
{
|
{
|
||||||
idx = idx - 1;
|
if (stake_mark > MAX_CHARGER_COUNT)
|
||||||
if (idx < 2)
|
|
||||||
{
|
{
|
||||||
memcpy(serial, g_charger_manager.charger_piles[stake_mark - 1].guns[idx].real_time_data.trade_serial, TRADE_SERIAL_LENGTH);
|
return;
|
||||||
}
|
}
|
||||||
|
if (idx > MAX_GUN_PER_CHARGER)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(serial, g_charger_manager.charger_piles[stake_mark - 1].guns[idx - 1].real_time_data.trade_serial, TRADE_SERIAL_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t is_my_charger_serial(uint8_t stake_mark, uint8_t *serial)
|
uint8_t is_my_charger_serial(uint8_t stake_mark, uint8_t *serial)
|
||||||
@@ -224,10 +220,10 @@ void pack_and_send_server_data(uint8_t type, uint8_t *pdata, uint8_t len, uint8_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 原子获取全局包序号,避免多任务竞争 */
|
/* 原子获取全局包序号,避免多任务竞争 */
|
||||||
// taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
current_serial = pack_serial;
|
current_serial = pack_serial;
|
||||||
pack_serial++;
|
pack_serial++;
|
||||||
// taskEXIT_CRITICAL();
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
buf[index++] = 0x55;
|
buf[index++] = 0x55;
|
||||||
buf[index++] = 0xAA;
|
buf[index++] = 0xAA;
|
||||||
@@ -251,6 +247,15 @@ void pack_and_send_server_data(uint8_t type, uint8_t *pdata, uint8_t len, uint8_
|
|||||||
buf[index++] = (crc >> 8) & 0xFF;
|
buf[index++] = (crc >> 8) & 0xFF;
|
||||||
buf[index++] = 0xAA;
|
buf[index++] = 0xAA;
|
||||||
buf[index++] = 0x55;
|
buf[index++] = 0x55;
|
||||||
|
|
||||||
|
if (type == FRAME_TYPE_0X3B)
|
||||||
|
{
|
||||||
|
printf("北向:0x3B 原始数据(%d字节): ", index);
|
||||||
|
for (uint16_t i = 0; i < index; i++)
|
||||||
|
printf("%02X ", buf[i]);
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
Air724_Message_Send(buf, index);
|
Air724_Message_Send(buf, index);
|
||||||
vPortFree(buf);
|
vPortFree(buf);
|
||||||
}
|
}
|
||||||
@@ -243,6 +243,38 @@ typedef struct
|
|||||||
uint32_t charger_motor_no; // 充电桩电机编号
|
uint32_t charger_motor_no; // 充电桩电机编号
|
||||||
} __attribute__((packed)) PACK_DATA_0X19; // 0x19
|
} __attribute__((packed)) PACK_DATA_0X19; // 0x19
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t trade_serial[TRADE_SERIAL_LENGTH]; // 交易流水号
|
||||||
|
uint8_t charger_serial[CHARGER_SERIAL_LENGTH]; // 桩编号
|
||||||
|
uint8_t gun_index; // 枪号
|
||||||
|
uint16_t bms_vol_demand; // BMS电压需求 0.1V/位
|
||||||
|
uint16_t bms_cur_demand; // BMS电流需求 0.1A/位, -400A偏移
|
||||||
|
uint8_t bms_charge_mode; // BMS充电模式 0x01:恒压 0x02:恒流
|
||||||
|
uint16_t bms_vol_measure; // BMS充电电压测量值 0.1V/位
|
||||||
|
uint16_t bms_cur_measure; // BMS充电电流测量值 0.1A/位, -400A偏移
|
||||||
|
uint16_t bms_max_cell_vol; // BMS最高单体电压及组号 低12位:0.01V/位 高4位:组号
|
||||||
|
uint8_t bms_soc; // BMS当前SOC 1%/位 0~100%
|
||||||
|
uint16_t bms_remain_time; // BMS估算剩余充电时间 1min/位 0~600min
|
||||||
|
uint16_t charger_vol_output; // 电桩电压输出值 0.1V/位
|
||||||
|
uint16_t charger_cur_output; // 电桩电流输出值 0.1A/位, -400A偏移
|
||||||
|
uint16_t charge_time; // 累计充电时间 1min/位 0~600min
|
||||||
|
} __attribute__((packed)) PACK_DATA_0X23; // 0x23
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t trade_serial[TRADE_SERIAL_LENGTH]; // 交易流水号
|
||||||
|
uint8_t charger_serial[CHARGER_SERIAL_LENGTH]; // 桩编号
|
||||||
|
uint8_t gun_index; // 枪号
|
||||||
|
uint8_t bms_max_cell_vol_num; // BMS最高单体电压所在编号 1/位,1偏移 1~256
|
||||||
|
uint8_t bms_max_temp; // BMS最高动力蓄电池温度 1°C/位,-50°C偏移
|
||||||
|
uint8_t max_temp_point_num; // 最高温度检测点编号 1/位,1偏移 1~128
|
||||||
|
uint8_t bms_min_temp; // 最低动力蓄电池温度 1°C/位,-50°C偏移
|
||||||
|
uint8_t min_temp_point_num; // 最低温度检测点编号 1/位,1偏移 1~128
|
||||||
|
uint8_t bms_alarm_1; // 位0-1:单体电压过高/过低 位2-3:SOC过高/过低 位4-5:充电过流 位6-7:温度过高 (<00>:正常 <01>:过高 <10>:过低)
|
||||||
|
uint8_t bms_alarm_2; // 位0-1:绝缘状态 位2-3:输出连接器状态 位4-5:充电禁止 位6-7:预留 (<00>:正常 <01>:异常 <10>:不可信)
|
||||||
|
} __attribute__((packed)) PACK_DATA_0X25; // 0x25
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t charger_serial[CHARGER_SERIAL_LENGTH]; // 桩编号
|
uint8_t charger_serial[CHARGER_SERIAL_LENGTH]; // 桩编号
|
||||||
@@ -306,13 +338,11 @@ typedef struct
|
|||||||
uint8_t trade_serial[TRADE_SERIAL_LENGTH]; // 交易流水号
|
uint8_t trade_serial[TRADE_SERIAL_LENGTH]; // 交易流水号
|
||||||
uint8_t charger_serial[CHARGER_SERIAL_LENGTH]; // 桩编号
|
uint8_t charger_serial[CHARGER_SERIAL_LENGTH]; // 桩编号
|
||||||
uint8_t gun_index; // 枪编号
|
uint8_t gun_index; // 枪编号
|
||||||
|
|
||||||
|
|
||||||
uint8_t start_time[7]; // 开始时间
|
uint8_t start_time[7]; // 开始时间
|
||||||
uint8_t end_time[7]; // 结束时间
|
uint8_t end_time[7]; // 结束时间
|
||||||
|
|
||||||
uint8_t meter_id[6];
|
|
||||||
uint8_t meter_ciphertext[34];
|
|
||||||
uint8_t meter_protocol_version[2];
|
|
||||||
uint8_t encryption_type;
|
|
||||||
uint32_t shark_price; // 尖单价
|
uint32_t shark_price; // 尖单价
|
||||||
uint32_t shark_energy; // 尖电量
|
uint32_t shark_energy; // 尖电量
|
||||||
uint32_t loss_shark_energy; // 计损尖电量
|
uint32_t loss_shark_energy; // 计损尖电量
|
||||||
@@ -340,7 +370,7 @@ typedef struct
|
|||||||
uint32_t consumption; // 消费金额
|
uint32_t consumption; // 消费金额
|
||||||
uint8_t vin[17]; // 电动汽车唯一标识
|
uint8_t vin[17]; // 电动汽车唯一标识
|
||||||
uint8_t trade_flag; // 交易标识
|
uint8_t trade_flag; // 交易标识
|
||||||
uint8_t trade_data[7]; // 交易日期
|
uint8_t trade_time[7]; // 交易时间
|
||||||
uint8_t stop_reason; // 停止原因
|
uint8_t stop_reason; // 停止原因
|
||||||
uint8_t phy_cardid[8]; // 物理卡号
|
uint8_t phy_cardid[8]; // 物理卡号
|
||||||
} __attribute__((packed)) PACK_DATA_0X3B; // 0x3B
|
} __attribute__((packed)) PACK_DATA_0X3B; // 0x3B
|
||||||
@@ -1,6 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @file server_to_charger.c
|
||||||
|
* @brief 充电桩通信协议处理模块 下行数据
|
||||||
|
* @details 处理充电桩与服务器之间的通信协议,包括登录认证应答、心跳应答、计费模型验证应答、
|
||||||
|
* 等功能。支持字节码格式的数据交互,通过串口协议与服务器通信。
|
||||||
|
* @date 2025-01-09 14:32:15
|
||||||
|
* @version 1.0.0
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*/
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "server_to_charger.h"
|
#include "server_to_charger.h"
|
||||||
|
#include "point_protocol.h"
|
||||||
|
#include "host_computer_protocol.h"
|
||||||
// 登录认证应答
|
// 登录认证应答
|
||||||
void on_cmd_frame_type_0X02(uint8_t stake_index, SERVER_PACK *pack)
|
void on_cmd_frame_type_0X02(uint8_t stake_index, SERVER_PACK *pack)
|
||||||
{
|
{
|
||||||
@@ -132,16 +142,17 @@ void on_cmd_frame_type_0X58(uint8_t stake_index, SERVER_PACK *pack)
|
|||||||
{
|
{
|
||||||
|
|
||||||
g_charger_manager.fee_model_global = data.model;
|
g_charger_manager.fee_model_global = data.model;
|
||||||
|
g_charger_manager.charger_piles[stake_index - 1].get_model = true;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
char str[150];
|
|
||||||
Rs485_Message_Send("t0.txt=\"\"\xff\xff\xff", 12);
|
|
||||||
printf("北向:接收到计费模型应答,模型ID:%d\r\n", g_charger_manager.fee_model_global.fee_model_no);
|
printf("北向:接收到计费模型应答,模型ID:%d\r\n", g_charger_manager.fee_model_global.fee_model_no);
|
||||||
printf("尖电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.shark_fee_ratio, g_charger_manager.fee_model_global.shark_service_ratio);
|
printf("尖电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.shark_fee_ratio, g_charger_manager.fee_model_global.shark_service_ratio);
|
||||||
printf("峰电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.peak_fee_ratio, g_charger_manager.fee_model_global.peak_service_ratio);
|
printf("峰电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.peak_fee_ratio, g_charger_manager.fee_model_global.peak_service_ratio);
|
||||||
printf("平电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.flat_fee_ratio, g_charger_manager.fee_model_global.flat_service_ratio);
|
printf("平电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.flat_fee_ratio, g_charger_manager.fee_model_global.flat_service_ratio);
|
||||||
printf("谷电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.valley_fee_ratio, g_charger_manager.fee_model_global.valley_service_ratio);
|
printf("谷电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.valley_fee_ratio, g_charger_manager.fee_model_global.valley_service_ratio);
|
||||||
printf("计损比例: %d%% \r\n", g_charger_manager.fee_model_global.loss_ratio);
|
printf("计损比例: %d%% \r\n", g_charger_manager.fee_model_global.loss_ratio);
|
||||||
|
|
||||||
printf("\n合并后的费率时间段 :\r\n");
|
printf("\n合并后的费率时间段 :\r\n");
|
||||||
printf("================================================================\r\n");
|
printf("================================================================\r\n");
|
||||||
|
|
||||||
@@ -192,15 +203,16 @@ void on_cmd_frame_type_0X58(uint8_t stake_index, SERVER_PACK *pack)
|
|||||||
end_hour = 0;
|
end_hour = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%02d:%02d-%02d:%02d 为 %s 费率\r",
|
printf("%02d:%02d-%02d:%02d 为 %s 费率\r\n",
|
||||||
start_hour, start_min,
|
start_hour, start_min,
|
||||||
end_hour, end_min,
|
end_hour, end_min,
|
||||||
fee_name);
|
fee_name);
|
||||||
|
|
||||||
i = j; // 跳到下一个不同费率段
|
i = j; // 跳到下一个不同费率段
|
||||||
}
|
}
|
||||||
printf("================================================================\r\n");
|
printf("================================================================\r\n");
|
||||||
charger_to_server_0x57(stake_index);
|
|
||||||
#endif
|
#endif
|
||||||
|
charger_to_server_0x57(stake_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,46 +224,26 @@ void on_cmd_frame_type_0X34(uint8_t stake_index, SERVER_PACK *pack)
|
|||||||
uint8_t err_code = 0; // 默认错误码为0
|
uint8_t err_code = 0; // 默认错误码为0
|
||||||
memcpy(&data, pack->data, sizeof(PACK_DATA_0X34));
|
memcpy(&data, pack->data, sizeof(PACK_DATA_0X34));
|
||||||
set_trade_serial(stake_index, data.gun_index, data.trade_serial);
|
set_trade_serial(stake_index, data.gun_index, data.trade_serial);
|
||||||
printf("北向:平台控制充电,桩ID:%d, 枪ID:%d, 金额:%d\r\n", stake_index, data.gun_index, data.remain_money);
|
printf(" └── [info] 桩ID:%d, 枪ID:%d, 金额:%d\r\n", stake_index, data.gun_index, data.remain_money);
|
||||||
|
|
||||||
uint8_t *trade_serial = data.trade_serial;
|
if (is_my_charger_serial(stake_index, data.charger_serial) == FALSE)
|
||||||
|
|
||||||
memcpy(g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.trade_serial, data.trade_serial, 16);
|
|
||||||
|
|
||||||
if (!is_my_charger_serial(stake_index, data.charger_serial))
|
|
||||||
{
|
{
|
||||||
result = 0;
|
result = 0;
|
||||||
err_code = 0x1; // 桩编号不匹配
|
err_code = 0x1; // 桩编号不匹配
|
||||||
}
|
|
||||||
else if (g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.status == 3)
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
err_code = 0x2; // 枪在使用
|
|
||||||
}
|
|
||||||
else if (g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.status == 1)
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
err_code = 0x3; // 枪故障
|
|
||||||
}
|
|
||||||
else if (g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.status == 0)
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
err_code = 0x4; // 枪离线
|
|
||||||
}
|
|
||||||
else if (g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.gun_is_insert == FALSE)
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
err_code = 0x5; // 未插枪
|
|
||||||
}
|
|
||||||
|
|
||||||
charger_to_server_0X33(stake_index, data.gun_index, result, err_code);
|
charger_to_server_0X33(stake_index, data.gun_index, result, err_code);
|
||||||
|
g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].charger_state = FAIL_CHARGER_STATE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
point_send_start_charging(stake_index, data.gun_index);
|
||||||
|
g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].charger_state = REDAY_CHARGER_START_STATE;
|
||||||
|
printf(" └── [info] 等待桩启动回应...\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 平台控制停止充电
|
// 平台控制停止充电
|
||||||
void on_cmd_frame_type_0X36(uint8_t stake_index, SERVER_PACK *pack)
|
void on_cmd_frame_type_0X36(uint8_t stake_index, SERVER_PACK *pack)
|
||||||
{
|
{
|
||||||
PACK_DATA_0X36 data;
|
PACK_DATA_0X36 data;
|
||||||
uint8_t result = TRUE; // 默认启动结果成功
|
uint8_t result = TRUE; // 默认停止结果成功
|
||||||
uint8_t err_code = 0; // 默认错误码为0
|
uint8_t err_code = 0; // 默认错误码为0
|
||||||
memcpy(&data, pack->data, sizeof(PACK_DATA_0X36));
|
memcpy(&data, pack->data, sizeof(PACK_DATA_0X36));
|
||||||
printf("北向:平台控制停止充电,桩ID:%d, 枪ID:%d\r\n", stake_index, data.gun_index);
|
printf("北向:平台控制停止充电,桩ID:%d, 枪ID:%d\r\n", stake_index, data.gun_index);
|
||||||
@@ -267,5 +259,21 @@ void on_cmd_frame_type_0X36(uint8_t stake_index, SERVER_PACK *pack)
|
|||||||
err_code = 0x2; // 枪未在使用
|
err_code = 0x2; // 枪未在使用
|
||||||
}
|
}
|
||||||
|
|
||||||
charger_to_server_0X33(stake_index, data.gun_index, result, err_code);
|
charger_to_server_0X35(stake_index, data.gun_index, result, err_code);
|
||||||
|
|
||||||
|
point_send_stop_charging(stake_index, data.gun_index);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 平台接收到交易记录
|
||||||
|
void on_cmd_frame_type_0X40(uint8_t stake_index, SERVER_PACK *pack)
|
||||||
|
{
|
||||||
|
PACK_DATA_0X40 data;
|
||||||
|
memcpy(&data, pack->data, sizeof(PACK_DATA_0X40));
|
||||||
|
printf("北向:平台接收到交易记录,桩ID:%d, 交易记录:%s\r\n", stake_index, data.trade_serial);
|
||||||
|
if (data.result == 0)
|
||||||
|
{
|
||||||
|
printf("1234567890987654324567898765434567890-98765165165165*************************************成功\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,5 +10,7 @@ void on_cmd_frame_type_0X0A(uint8_t stake_index,SERVER_PACK *pack);
|
|||||||
void on_cmd_frame_type_0X06(uint8_t stake_index,SERVER_PACK *pack);
|
void on_cmd_frame_type_0X06(uint8_t stake_index,SERVER_PACK *pack);
|
||||||
void on_cmd_frame_type_0X58(uint8_t stake_index,SERVER_PACK *pack);
|
void on_cmd_frame_type_0X58(uint8_t stake_index,SERVER_PACK *pack);
|
||||||
void on_cmd_frame_type_0X34(uint8_t stake_index,SERVER_PACK *pack);
|
void on_cmd_frame_type_0X34(uint8_t stake_index,SERVER_PACK *pack);
|
||||||
|
void on_cmd_frame_type_0X36(uint8_t stake_index,SERVER_PACK *pack);
|
||||||
|
void on_cmd_frame_type_0X40(uint8_t stake_index,SERVER_PACK *pack);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
34
Core/User/Protocol/Ykc/ykc_router.c
Normal file
34
Core/User/Protocol/Ykc/ykc_router.c
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "ykc_router.h"
|
||||||
|
|
||||||
|
static const ykc_route_entry_t YKC_ROUTE_TABLE[] = {
|
||||||
|
{FRAME_TYPE_0X02, on_cmd_frame_type_0X02, " 登录认证应答 "},
|
||||||
|
{FRAME_TYPE_0X04, on_cmd_frame_type_0X04, " 心跳应答 "},
|
||||||
|
{FRAME_TYPE_0X06, on_cmd_frame_type_0X06, " 计费模型验证应答 "},
|
||||||
|
{FRAME_TYPE_0X0A, on_cmd_frame_type_0X0A, " 获取计费模型 "},
|
||||||
|
{FRAME_TYPE_0X58, on_cmd_frame_type_0X58, " 计费模型设置 "},
|
||||||
|
{FRAME_TYPE_0X34, on_cmd_frame_type_0X34, " 平台启动充电 "},
|
||||||
|
{FRAME_TYPE_0X36, on_cmd_frame_type_0X36, " 平台控制停止充电 "},
|
||||||
|
{FRAME_TYPE_0X40, on_cmd_frame_type_0X40, " 平台接收到交易记录 "},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define YKC_ROUTE_TABLE_SIZE (sizeof(YKC_ROUTE_TABLE) / sizeof(YKC_ROUTE_TABLE[0]))
|
||||||
|
|
||||||
|
void ykc_route_dispatch(uint8_t stake_mark, SERVER_PACK *pack)
|
||||||
|
{
|
||||||
|
if (!pack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < YKC_ROUTE_TABLE_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (pack->frame_type == YKC_ROUTE_TABLE[i].frame_type)
|
||||||
|
{
|
||||||
|
printf("[YKC Router] frame=0x%02X │ stake=%d │ %s\r\n",
|
||||||
|
pack->frame_type, stake_mark, YKC_ROUTE_TABLE[i].desc);
|
||||||
|
YKC_ROUTE_TABLE[i].handler(stake_mark, pack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[YKC Router] 未知帧类型: 0x%02X from stake %d\r\n",
|
||||||
|
pack->frame_type, stake_mark);
|
||||||
|
}
|
||||||
19
Core/User/Protocol/Ykc/ykc_router.h
Normal file
19
Core/User/Protocol/Ykc/ykc_router.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef __YKC_ROUTER_H
|
||||||
|
#define __YKC_ROUTER_H
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
#include "server_common.h"
|
||||||
|
#include "server_to_charger.h"
|
||||||
|
|
||||||
|
typedef void (*ykc_handler_t)(uint8_t stake_index, SERVER_PACK *pack);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t frame_type; /* 帧类型(匹配键) */
|
||||||
|
ykc_handler_t handler; /* 处理函数 */
|
||||||
|
const char *desc; /* 描述(日志用) */
|
||||||
|
} ykc_route_entry_t;
|
||||||
|
|
||||||
|
void ykc_route_dispatch(uint8_t stake_mark, SERVER_PACK *pack);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,793 +0,0 @@
|
|||||||
#include "ChargerTask.h"
|
|
||||||
|
|
||||||
static struct netconn *datalink_conn; // 数据链路句柄
|
|
||||||
#define LINK_SERVER_PORT 6001 // 网关UDP服务端口
|
|
||||||
#define LINK_STAKE_PORT 6001 // 桩通讯端口
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 桩IP地址
|
|
||||||
* @note 桩IP地址从10.12.19.101开始递增
|
|
||||||
*/
|
|
||||||
ip4_addr_t stake_ip_1 = IPADDR4_INIT_BYTES(10, 12, 19, 101); // 桩 1 IP地址
|
|
||||||
ip4_addr_t stake_ip_2 = IPADDR4_INIT_BYTES(10, 12, 19, 102); // 桩 2 IP地址
|
|
||||||
ip4_addr_t stake_ip_3 = IPADDR4_INIT_BYTES(10, 12, 19, 103); // 桩 3 IP地址
|
|
||||||
ip4_addr_t stake_ip_4 = IPADDR4_INIT_BYTES(10, 12, 19, 104); // 桩 4 IP地址
|
|
||||||
ip4_addr_t stake_ip_5 = IPADDR4_INIT_BYTES(10, 12, 19, 105); // 桩 5 IP地址
|
|
||||||
ip4_addr_t stake_ip_6 = IPADDR4_INIT_BYTES(10, 12, 19, 106); // 桩 6 IP地址
|
|
||||||
|
|
||||||
ip4_addr_t server_ip = IPADDR4_INIT_BYTES(10, 12, 19, 107); // 上位机管理地址
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将十六进制字符串转换为字节数组
|
|
||||||
* @note 输入字符串长度必须为偶数
|
|
||||||
*/
|
|
||||||
int hex_string_to_bytes(const char *hex_str, uint8_t *bytes, int len)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
unsigned int val;
|
|
||||||
sscanf(hex_str + i * 2, "%02x", &val);
|
|
||||||
bytes[i] = (uint8_t)val;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将字节数组转换为十六进制字符串
|
|
||||||
* @note 输出字符串长度必须为32
|
|
||||||
*/
|
|
||||||
void bytes_to_hex_string(const uint8_t *bytes, char *hex_str)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
sprintf(hex_str + i * 2, "%02X", bytes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @brief UDP发送
|
|
||||||
* @note 发送数据到指定桩
|
|
||||||
* @param stake_index 目标桩ID
|
|
||||||
* @param data 数据指针
|
|
||||||
* @param len 数据长度
|
|
||||||
* @return err_t 错误码
|
|
||||||
*/
|
|
||||||
err_t udp_send_response(uint8_t stake_index, uint8_t *data, u16_t len)
|
|
||||||
{
|
|
||||||
struct netbuf *buf = netbuf_new();
|
|
||||||
if (!buf)
|
|
||||||
{
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip4_addr_t *dst_ip = NULL;
|
|
||||||
switch (stake_index)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
dst_ip = &stake_ip_1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
dst_ip = &stake_ip_2;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
dst_ip = &stake_ip_3;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
dst_ip = &stake_ip_4;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
dst_ip = &stake_ip_5;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
dst_ip = &stake_ip_6;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
dst_ip = &server_ip;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Invalid stake index\r\n");
|
|
||||||
netbuf_delete(buf);
|
|
||||||
return ERR_VAL; // ← 修复 return 无返回值
|
|
||||||
}
|
|
||||||
|
|
||||||
void *buf_data = netbuf_alloc(buf, len); // ← 在 netbuf 内部分配内存
|
|
||||||
if (!buf_data)
|
|
||||||
{
|
|
||||||
netbuf_delete(buf);
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
memcpy(buf_data, data, len); // ← 拷贝数据,不再依赖外部指针
|
|
||||||
|
|
||||||
err_t err = netconn_sendto(datalink_conn, buf, dst_ip, LINK_STAKE_PORT);
|
|
||||||
netbuf_delete(buf);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UDP_ParseTask_Function(void const *argument)
|
|
||||||
{
|
|
||||||
UdpMsg_t msg;
|
|
||||||
cJSON *root = NULL, *cmd = NULL, *id = NULL;
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); /* 等待桩通讯协议层完成*/
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (xQueueReceive(UDP_Message_Queue, &msg, portMAX_DELAY) == pdPASS)
|
|
||||||
{
|
|
||||||
root = cJSON_Parse((const char *)msg.data);
|
|
||||||
if (root == NULL)
|
|
||||||
{
|
|
||||||
printf("JSON Parse Failed: %s\r\n", msg.data);
|
|
||||||
vPortFree(msg.data);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
id = cJSON_GetObjectItem(root, "id");
|
|
||||||
cmd = cJSON_GetObjectItem(root, "cmd");
|
|
||||||
|
|
||||||
if (cmd != NULL && id != NULL)
|
|
||||||
{
|
|
||||||
const char *cmd_str = cmd->valuestring;
|
|
||||||
handle_udp_downlink((uint8_t)id->valueint, cmd_str, root);
|
|
||||||
cJSON_Delete(root);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Missing 'code' field from \r\n");
|
|
||||||
cJSON_Delete(root);
|
|
||||||
}
|
|
||||||
vPortFree(msg.data);
|
|
||||||
msg.data = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief UPLinkTask_Function:桩通讯任务
|
|
||||||
*
|
|
||||||
* @note none
|
|
||||||
*
|
|
||||||
* @param taskID : 任务ID
|
|
||||||
*
|
|
||||||
* @retval runtime : 任务周期
|
|
||||||
*/
|
|
||||||
|
|
||||||
void UDPTask_Function(void const *argument)
|
|
||||||
{
|
|
||||||
err_t recv_err;
|
|
||||||
struct netbuf *datalink_buf = NULL;
|
|
||||||
datalink_conn = netconn_new(NETCONN_UDP);
|
|
||||||
netconn_bind(datalink_conn, IP_ADDR_ANY, LINK_SERVER_PORT);
|
|
||||||
UDP_Message_Queue_Init(); // 初始化UDP接收队列
|
|
||||||
/*桩UDP通讯初始化完成 发送云快充任务通知*/
|
|
||||||
xTaskNotifyGive(YkcTaskHandle);
|
|
||||||
xTaskNotifyGive(DownLinkTaskHandle);
|
|
||||||
xTaskNotifyGive(UDP_ParseTaskHandle);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
/*获取任务运行状态*/
|
|
||||||
TaskRunTimeStat.UPLinkTask.threads_runtime = GetTask_RunTime(UPLinkTaskID);
|
|
||||||
TaskRunTimeStat.UPLinkTask.threads_counter = GetTask_Beatcnt(UPLinkTaskID);
|
|
||||||
TaskRunTimeStat.UPLinkTask.threads_freestack = Get_Free_Stack(UPLinkTaskID);
|
|
||||||
|
|
||||||
recv_err = netconn_recv(datalink_conn, &datalink_buf);
|
|
||||||
|
|
||||||
if (recv_err == ERR_OK && datalink_buf != NULL)
|
|
||||||
{
|
|
||||||
uint8_t *playload;
|
|
||||||
uint16_t playload_len;
|
|
||||||
netbuf_data(datalink_buf, (void *)&playload, &playload_len);
|
|
||||||
if (playload_len > 0)
|
|
||||||
{
|
|
||||||
UdpMsg_t msg;
|
|
||||||
ip_addr_copy(msg.src_ip, *netbuf_fromaddr(datalink_buf)); // 获取UDP源IP
|
|
||||||
msg.src_port = netbuf_fromport(datalink_buf); // 获取UDP源端口
|
|
||||||
msg.len = playload_len;
|
|
||||||
msg.data = (char *)pvPortMalloc(playload_len + 1);
|
|
||||||
if (msg.data != NULL)
|
|
||||||
{
|
|
||||||
memcpy(msg.data, playload, playload_len);
|
|
||||||
msg.data[playload_len] = '\0';
|
|
||||||
// 队列满,释放数据内存
|
|
||||||
if (xQueueSend(UDP_Message_Queue, &msg, 0) != pdPASS)
|
|
||||||
{
|
|
||||||
vPortFree(msg.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
netbuf_delete(datalink_buf); // 释放UDP网络缓冲区
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (recv_err != ERR_TIMEOUT && recv_err != ERR_WOULDBLOCK)
|
|
||||||
{
|
|
||||||
printf("datalink netconn_recv err: %d\r\n", recv_err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 解析充电桩上电指令
|
|
||||||
* @note 设置桩为本地在线状态,发送上电应答
|
|
||||||
* @param stake_index 桩索引
|
|
||||||
* @param json_pack json数据包
|
|
||||||
*/
|
|
||||||
void local_on_cmd_callback_power_on(uint8_t stake_index, cJSON *json_pack)
|
|
||||||
{
|
|
||||||
if (stake_index > MAX_CHARGER_COUNT)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
g_charger_manager.charger_piles[stake_index - 1].is_udp_online = true; // 设置桩为本地在线状态
|
|
||||||
|
|
||||||
cJSON *root = NULL;
|
|
||||||
uint8_t *str = NULL;
|
|
||||||
|
|
||||||
root = cJSON_CreateObject();
|
|
||||||
if (root == NULL)
|
|
||||||
{
|
|
||||||
printf("Failed to create JSON object for stake %d\r\n", stake_index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
|
|
||||||
cJSON_AddNumberToObject(root, "id", stake_index);
|
|
||||||
cJSON_AddStringToObject(root, "cmd", "online");
|
|
||||||
cJSON_AddStringToObject(root, "type", "response");
|
|
||||||
|
|
||||||
str = cJSON_Print(root);
|
|
||||||
udp_send_response(stake_index, str, strlen(str));
|
|
||||||
free(str);
|
|
||||||
cJSON_Delete(root);
|
|
||||||
|
|
||||||
printf("南向:对电桩 %d 上电回复成功\r\n", stake_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 解析充电桩心跳指令
|
|
||||||
* @note 回复心跳应答
|
|
||||||
* @param stake_index 桩索引
|
|
||||||
* @param json_pack json数据包
|
|
||||||
*/
|
|
||||||
void local_on_cmd_callback_heartbeat_response(uint8_t stake_index, cJSON *json_pack)
|
|
||||||
{
|
|
||||||
if (stake_index > MAX_CHARGER_COUNT)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 心跳unpack
|
|
||||||
|
|
||||||
cJSON *gun_array = cJSON_GetObjectItem(json_pack, "gun");
|
|
||||||
// 直接判断 type 字段
|
|
||||||
if (gun_array == NULL || gun_array->type != cJSON_Array)
|
|
||||||
{
|
|
||||||
printf(" └── [error] 缺少 gun 数组\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gun_count = cJSON_GetArraySize(gun_array);
|
|
||||||
for (int i = 0; i < gun_count; i++)
|
|
||||||
{
|
|
||||||
cJSON *gun = cJSON_GetArrayItem(gun_array, i);
|
|
||||||
if (!gun)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
cJSON *id = cJSON_GetObjectItem(gun, "id");
|
|
||||||
cJSON *state = cJSON_GetObjectItem(gun, "state");
|
|
||||||
|
|
||||||
if (!id || !state)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// if (id->valueint == 1) pile->gun1_state = state->valueint;
|
|
||||||
// if (id->valueint == 2) pile->gun2_state = state->valueint;
|
|
||||||
printf(" └── [info] 桩%d 枪%d state=%d\r\n", stake_index, id->valueint, state->valueint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 心跳回复组包
|
|
||||||
cJSON *root = NULL;
|
|
||||||
char *str = NULL;
|
|
||||||
|
|
||||||
root = cJSON_CreateObject();
|
|
||||||
if (root == NULL)
|
|
||||||
{
|
|
||||||
printf("Failed to create JSON object for stake %d\r\n", stake_index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
|
|
||||||
cJSON_AddNumberToObject(root, "id", stake_index);
|
|
||||||
cJSON_AddStringToObject(root, "cmd", "heartbeat");
|
|
||||||
cJSON_AddStringToObject(root, "type", "response");
|
|
||||||
|
|
||||||
str = cJSON_Print(root);
|
|
||||||
udp_send_response(stake_index, str, strlen(str));
|
|
||||||
free(str);
|
|
||||||
cJSON_Delete(root);
|
|
||||||
|
|
||||||
printf("南向:对电桩 %d 心跳回复成功\r\n", stake_index);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @brief 解析充电桩实时数据指令
|
|
||||||
* @note 回复实时数据应答
|
|
||||||
* @param stake_index 桩索引
|
|
||||||
* @param json_pack json数据包
|
|
||||||
*/
|
|
||||||
void local_on_cmd_callback_realtime_data_response(uint8_t stake_index, cJSON *json_pack)
|
|
||||||
{
|
|
||||||
if (stake_index > MAX_CHARGER_COUNT)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON *transaction_id = cJSON_GetObjectItem(json_pack, "transaction_id"); // 提取交易序列号
|
|
||||||
cJSON *gun_id = cJSON_GetObjectItem(json_pack, "gun_id"); // 提取枪号
|
|
||||||
cJSON *state = cJSON_GetObjectItem(json_pack, "state"); // 提取枪状态
|
|
||||||
cJSON *gun_back = cJSON_GetObjectItem(json_pack, "gun_back"); // 提取枪归位状态
|
|
||||||
cJSON *gun_insert = cJSON_GetObjectItem(json_pack, "gun_insert"); // 提取枪插入状态
|
|
||||||
cJSON *voltage = cJSON_GetObjectItem(json_pack, "voltage"); // 提取电压
|
|
||||||
cJSON *current = cJSON_GetObjectItem(json_pack, "current"); // 提取电流
|
|
||||||
cJSON *cable_temp = cJSON_GetObjectItem(json_pack, "cable_temp"); // 提取电缆温度
|
|
||||||
cJSON *cable_code = cJSON_GetObjectItem(json_pack, "cable_code"); // 提取电缆编码
|
|
||||||
cJSON *soc = cJSON_GetObjectItem(json_pack, "soc"); // 提取SOC
|
|
||||||
cJSON *battery_temp = cJSON_GetObjectItem(json_pack, "battery_temp"); // 提取电池温度
|
|
||||||
cJSON *charge_time = cJSON_GetObjectItem(json_pack, "charge_time"); // 提取充电时间
|
|
||||||
cJSON *remain_time = cJSON_GetObjectItem(json_pack, "remain_time"); // 提取剩余时间
|
|
||||||
cJSON *charge_kwh = cJSON_GetObjectItem(json_pack, "charge_kwh"); // 提取充电量
|
|
||||||
cJSON *loss_kwh = cJSON_GetObjectItem(json_pack, "loss_kwh"); // 提取损失量
|
|
||||||
cJSON *charge_amount = cJSON_GetObjectItem(json_pack, "charge_amount"); // 提取充电金额
|
|
||||||
cJSON *fault = cJSON_GetObjectItem(json_pack, "fault"); // 提取故障状态
|
|
||||||
// 检查交易序列号、枪号、状态字段是否存在
|
|
||||||
if (!transaction_id || !gun_id || !state)
|
|
||||||
{
|
|
||||||
printf(" └── [error] 缺少必要字段 transaction_id/gun_id/state\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 检查交易序列号长度是否为32位
|
|
||||||
if (strlen(transaction_id->valuestring) != 32)
|
|
||||||
{
|
|
||||||
printf(" └── [error] transaction_id长度错误: %d\r\n", (int)strlen(transaction_id->valuestring));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 检查枪号是否有效
|
|
||||||
uint8_t gun_idx = (uint8_t)gun_id->valueint;
|
|
||||||
if (gun_idx == 0 || gun_idx > MAX_GUN_PER_CHARGER)
|
|
||||||
{
|
|
||||||
printf(" └── [error] 无效的gun_id: %d\r\n", gun_idx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChargerPile *pile = &g_charger_manager.charger_piles[stake_index - 1];
|
|
||||||
ChargerGun *gun = &pile->guns[gun_idx - 1];
|
|
||||||
|
|
||||||
// 更新枪状态
|
|
||||||
gun->real_time_data.status = (uint8_t)state->valueint;
|
|
||||||
// 更新枪归位状态
|
|
||||||
gun->real_time_data.gun_back = (uint8_t)gun_back->valueint;
|
|
||||||
// 更新枪插入状态
|
|
||||||
gun->real_time_data.gun_is_insert = (uint8_t)gun_insert->valueint;
|
|
||||||
// 更新电压
|
|
||||||
gun->real_time_data.out_voltage = (uint16_t)(voltage->valuedouble * 10);
|
|
||||||
// 更新电流
|
|
||||||
gun->real_time_data.out_current = (uint16_t)(current->valuedouble * 10);
|
|
||||||
// 更新电缆温度
|
|
||||||
gun->real_time_data.gun_line_temp = (uint8_t)cable_temp->valueint;
|
|
||||||
// 更新SOC
|
|
||||||
gun->real_time_data.soc = (uint8_t)soc->valueint;
|
|
||||||
// 更新电池温度
|
|
||||||
gun->real_time_data.battery_temp = (uint8_t)battery_temp->valueint;
|
|
||||||
// 更新累计充电时间
|
|
||||||
gun->real_time_data.charge_time = (uint16_t)charge_time->valueint;
|
|
||||||
// 更新剩余时间
|
|
||||||
gun->real_time_data.remain_time = (uint16_t)remain_time->valueint;
|
|
||||||
// 更新充电量
|
|
||||||
gun->real_time_data.charge_energy = (uint32_t)(charge_kwh->valuedouble * 10000);
|
|
||||||
// 更新损失量
|
|
||||||
gun->real_time_data.loss_energy = (uint32_t)(loss_kwh->valuedouble * 10000);
|
|
||||||
// 更新充电金额
|
|
||||||
gun->real_time_data.charge_money = (uint32_t)(charge_amount->valuedouble * 10000);
|
|
||||||
// 更新故障状态
|
|
||||||
gun->real_time_data.hard_fault = (uint16_t)fault->valueint;
|
|
||||||
|
|
||||||
// 回复实时数据应答
|
|
||||||
cJSON *root = NULL;
|
|
||||||
char *str = NULL;
|
|
||||||
|
|
||||||
root = cJSON_CreateObject();
|
|
||||||
if (root == NULL)
|
|
||||||
{
|
|
||||||
printf("Failed to create JSON object for stake %d\r\n", stake_index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
|
|
||||||
cJSON_AddNumberToObject(root, "id", stake_index);
|
|
||||||
cJSON_AddStringToObject(root, "cmd", "realtime data");
|
|
||||||
cJSON_AddStringToObject(root, "type", "response");
|
|
||||||
|
|
||||||
str = cJSON_Print(root);
|
|
||||||
udp_send_response(stake_index, str, strlen(str));
|
|
||||||
free(str);
|
|
||||||
cJSON_Delete(root);
|
|
||||||
|
|
||||||
printf("南向:对电桩 %d 实时数据回复成功\r\n", stake_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 主动下发启动指令
|
|
||||||
* @note 发送启动指令到充电桩,符合协议格式要求
|
|
||||||
* @param stake_index 桩索引 (1~6)
|
|
||||||
* @param gun_id 枪编码 (1~N)
|
|
||||||
*/
|
|
||||||
void local_on_cmd_send_start_charging(uint8_t stake_index, uint8_t gun_id)
|
|
||||||
{
|
|
||||||
if (stake_index > 6 || stake_index == 0)
|
|
||||||
{
|
|
||||||
printf("Invalid stake index: %d\r\n", stake_index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gun_id == 0 || gun_id > MAX_GUN_PER_CHARGER)
|
|
||||||
{
|
|
||||||
printf("Invalid gun id: %d\r\n", gun_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否已获取费率模型
|
|
||||||
if (!g_charger_manager.charger_piles[stake_index - 1].get_model)
|
|
||||||
{
|
|
||||||
printf("Stake %d fee model not ready\r\n", stake_index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON *root = NULL;
|
|
||||||
cJSON *billing_array = NULL;
|
|
||||||
cJSON *billing_item = NULL;
|
|
||||||
char *str = NULL;
|
|
||||||
|
|
||||||
// 转换交易ID:16位数组转字符串
|
|
||||||
char transaction_id_str[33] = {0}; // 32位 + 结束符
|
|
||||||
uint8_t *trade_serial = g_charger_manager.charger_piles[stake_index - 1].guns[gun_id - 1].real_time_data.trade_serial;
|
|
||||||
trade_serial_to_string(trade_serial, transaction_id_str);
|
|
||||||
|
|
||||||
root = cJSON_CreateObject();
|
|
||||||
if (root == NULL)
|
|
||||||
{
|
|
||||||
printf("Failed to create JSON object for stake %d\r\n", stake_index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 添加基本字段 */
|
|
||||||
cJSON_AddNumberToObject(root, "id", stake_index);
|
|
||||||
cJSON_AddStringToObject(root, "cmd", "start charging");
|
|
||||||
cJSON_AddStringToObject(root, "transaction_id", transaction_id_str); // 使用转换后的32位字符串
|
|
||||||
cJSON_AddNumberToObject(root, "gun_id", gun_id);
|
|
||||||
cJSON_AddStringToObject(root, "type", "request");
|
|
||||||
|
|
||||||
/* 添加限制金额(根据实际业务设置)*/
|
|
||||||
cJSON_AddNumberToObject(root, "limit_amount", 00.00);
|
|
||||||
|
|
||||||
/* 创建计费模型数组 */
|
|
||||||
billing_array = cJSON_CreateArray();
|
|
||||||
if (billing_array == NULL)
|
|
||||||
{
|
|
||||||
printf("Failed to create billing array\r\n");
|
|
||||||
cJSON_Delete(root);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 计费时段:生成简化格式 [start_time, end_time, electricity_fee, service_fee] */
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (i < 48) // 48个半小时时段
|
|
||||||
{
|
|
||||||
uint8_t current_type = g_charger_manager.fee_model_global.fee_num[i];
|
|
||||||
|
|
||||||
// 跳过无效费率
|
|
||||||
if (current_type == 0xFF)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找连续相同费率的结束位置
|
|
||||||
int j = i;
|
|
||||||
while (j < 48 && g_charger_manager.fee_model_global.fee_num[j] == current_type)
|
|
||||||
{
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算起始时间(小时.半小时:6.0=6:00, 6.5=6:30)
|
|
||||||
float start_time = i * 0.5f;
|
|
||||||
float end_time = j * 0.5f;
|
|
||||||
|
|
||||||
// 跨天处理:24.0显示为0.0
|
|
||||||
if (end_time == 24.0f)
|
|
||||||
{
|
|
||||||
end_time = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据费率类型设置电费和服务费
|
|
||||||
float electricity_fee = 0.0f;
|
|
||||||
float service_fee = 0.0f;
|
|
||||||
|
|
||||||
switch (current_type)
|
|
||||||
{
|
|
||||||
case 0x00: // 尖时
|
|
||||||
electricity_fee = g_charger_manager.fee_model_global.shark_fee_ratio / 100000.0f;
|
|
||||||
service_fee = g_charger_manager.fee_model_global.shark_service_ratio / 100000.0f;
|
|
||||||
break;
|
|
||||||
case 0x01: // 峰时
|
|
||||||
electricity_fee = g_charger_manager.fee_model_global.peak_fee_ratio / 100000.0f;
|
|
||||||
service_fee = g_charger_manager.fee_model_global.peak_service_ratio / 100000.0f;
|
|
||||||
break;
|
|
||||||
case 0x02: // 平时
|
|
||||||
electricity_fee = g_charger_manager.fee_model_global.flat_fee_ratio / 100000.0f;
|
|
||||||
service_fee = g_charger_manager.fee_model_global.flat_service_ratio / 100000.0f;
|
|
||||||
break;
|
|
||||||
case 0x03: // 谷时
|
|
||||||
electricity_fee = g_charger_manager.fee_model_global.valley_fee_ratio / 100000.0f;
|
|
||||||
service_fee = g_charger_manager.fee_model_global.valley_service_ratio / 100000.0f;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
electricity_fee = 0.0f;
|
|
||||||
service_fee = 0.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建计费时段数组 [start_time, end_time, electricity_fee, service_fee]
|
|
||||||
if (electricity_fee > 0 || service_fee > 0)
|
|
||||||
{
|
|
||||||
billing_item = cJSON_CreateArray();
|
|
||||||
if (billing_item != NULL)
|
|
||||||
{
|
|
||||||
cJSON_AddNumberToObject(billing_item, NULL, start_time);
|
|
||||||
cJSON_AddNumberToObject(billing_item, NULL, end_time);
|
|
||||||
cJSON_AddNumberToObject(billing_item, NULL, electricity_fee);
|
|
||||||
cJSON_AddNumberToObject(billing_item, NULL, service_fee);
|
|
||||||
cJSON_AddItemToArray(billing_array, billing_item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i = j; // 跳到下一个不同费率段
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将数组添加到根对象
|
|
||||||
cJSON_AddItemToObject(root, "billing_model", billing_array);
|
|
||||||
|
|
||||||
// 转换为JSON字符串并发送
|
|
||||||
str = cJSON_Print(root);
|
|
||||||
if (str != NULL)
|
|
||||||
{
|
|
||||||
// #ifdef DEBUG
|
|
||||||
// printf("Send start command JSON: %s\r\n", str);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
udp_send_response(stake_index, str, strlen(str));
|
|
||||||
|
|
||||||
free(str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Failed to print JSON for stake %d\r\n", stake_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON_Delete(root);
|
|
||||||
printf("Southbound: Start command sent to stake %d, gun %d, total %d billing periods\r\n",
|
|
||||||
stake_index, gun_id, (int)cJSON_GetArraySize(billing_array));
|
|
||||||
}
|
|
||||||
|
|
||||||
void local_on_cmd_callback_server_login_response(cJSON *json_pack)
|
|
||||||
{
|
|
||||||
|
|
||||||
cJSON *request_id = cJSON_GetObjectItem(json_pack, "request_id");
|
|
||||||
cJSON *username = cJSON_GetObjectItem(json_pack, "username");
|
|
||||||
cJSON *password = cJSON_GetObjectItem(json_pack, "password");
|
|
||||||
|
|
||||||
cJSON *root = NULL;
|
|
||||||
char *str = NULL;
|
|
||||||
|
|
||||||
root = cJSON_CreateObject();
|
|
||||||
if (root == NULL)
|
|
||||||
{
|
|
||||||
printf("Failed to create JSON object for server login\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
|
|
||||||
cJSON_AddStringToObject(root, "request_id", request_id->valuestring);
|
|
||||||
|
|
||||||
if (strcmp(username->valuestring, "admin") != 0 || strcmp(password->valuestring, "123456") != 0)
|
|
||||||
{
|
|
||||||
cJSON_AddStringToObject(root, "error", "用户或密码错误 ");
|
|
||||||
cJSON_AddBoolToObject(root, "success", cJSON_False);
|
|
||||||
printf("登录失败\r\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cJSON_AddBoolToObject(root, "success", cJSON_True);
|
|
||||||
printf("登录成功\r\n");
|
|
||||||
}
|
|
||||||
str = cJSON_Print(root);
|
|
||||||
udp_send_response(7, str, strlen(str));
|
|
||||||
free(str);
|
|
||||||
cJSON_Delete(root);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理获取状态查询指令
|
|
||||||
void local_on_cmd_callback_server_get_status_response(cJSON *json_pack)
|
|
||||||
{
|
|
||||||
cJSON *request_id = cJSON_GetObjectItem(json_pack, "request_id");
|
|
||||||
|
|
||||||
cJSON *root = NULL;
|
|
||||||
cJSON *piles = NULL;
|
|
||||||
cJSON *pile = NULL;
|
|
||||||
cJSON *guns = NULL;
|
|
||||||
cJSON *gun = NULL;
|
|
||||||
char *str = NULL;
|
|
||||||
|
|
||||||
root = cJSON_CreateObject();
|
|
||||||
if (root == NULL)
|
|
||||||
{
|
|
||||||
printf("Failed to create JSON object for get_status\r");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON_AddStringToObject(root, "request_id", request_id->valuestring);
|
|
||||||
cJSON_AddBoolToObject(root, "success", cJSON_True);
|
|
||||||
|
|
||||||
/* ── piles 数组 ── */
|
|
||||||
piles = cJSON_CreateArray();
|
|
||||||
|
|
||||||
/* 桩 1 */
|
|
||||||
pile = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(pile, "serial", "32010601111558");
|
|
||||||
cJSON_AddBoolToObject(pile, "is_online", cJSON_True);
|
|
||||||
guns = cJSON_CreateArray();
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 1);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 0);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
cJSON_AddItemToObject(pile, "guns", guns);
|
|
||||||
cJSON_AddItemToArray(piles, pile);
|
|
||||||
|
|
||||||
/* 桩 2 */
|
|
||||||
pile = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(pile, "serial", "32010601111559");
|
|
||||||
cJSON_AddBoolToObject(pile, "is_online", cJSON_True);
|
|
||||||
guns = cJSON_CreateArray();
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 1);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 1);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
cJSON_AddItemToObject(pile, "guns", guns);
|
|
||||||
cJSON_AddItemToArray(piles, pile);
|
|
||||||
|
|
||||||
/* 桩 3 */
|
|
||||||
pile = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(pile, "serial", "32010601111560");
|
|
||||||
cJSON_AddBoolToObject(pile, "is_online", cJSON_True);
|
|
||||||
guns = cJSON_CreateArray();
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 0);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 0);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
cJSON_AddItemToObject(pile, "guns", guns);
|
|
||||||
cJSON_AddItemToArray(piles, pile);
|
|
||||||
|
|
||||||
/* 桩 4 */
|
|
||||||
pile = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(pile, "serial", "32010601111561");
|
|
||||||
cJSON_AddBoolToObject(pile, "is_online", cJSON_False);
|
|
||||||
guns = cJSON_CreateArray();
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 0);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 0);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
cJSON_AddItemToObject(pile, "guns", guns);
|
|
||||||
cJSON_AddItemToArray(piles, pile);
|
|
||||||
|
|
||||||
/* 桩 5 */
|
|
||||||
pile = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(pile, "serial", "32010601111562");
|
|
||||||
cJSON_AddBoolToObject(pile, "is_online", cJSON_True);
|
|
||||||
guns = cJSON_CreateArray();
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 1);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 0);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
cJSON_AddItemToObject(pile, "guns", guns);
|
|
||||||
cJSON_AddItemToArray(piles, pile);
|
|
||||||
|
|
||||||
/* 桩 6 */
|
|
||||||
pile = cJSON_CreateObject();
|
|
||||||
cJSON_AddStringToObject(pile, "serial", "32010601111563");
|
|
||||||
cJSON_AddBoolToObject(pile, "is_online", cJSON_False);
|
|
||||||
guns = cJSON_CreateArray();
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 0);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
gun = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(gun, "status", 0);
|
|
||||||
cJSON_AddItemToArray(guns, gun);
|
|
||||||
cJSON_AddItemToObject(pile, "guns", guns);
|
|
||||||
cJSON_AddItemToArray(piles, pile);
|
|
||||||
|
|
||||||
cJSON_AddItemToObject(root, "piles", piles);
|
|
||||||
|
|
||||||
/* ── 发送 ── */
|
|
||||||
str = cJSON_Print(root);
|
|
||||||
udp_send_response(7, str, strlen(str));
|
|
||||||
free(str);
|
|
||||||
cJSON_Delete(root);
|
|
||||||
printf("get_status 回复已发送 \r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_udp_downlink(uint8_t id, const char *cmd, cJSON *json_pack)
|
|
||||||
{
|
|
||||||
if (cmd == NULL)
|
|
||||||
return;
|
|
||||||
// 处理上电指令
|
|
||||||
if (strcmp(cmd, "online") == 0)
|
|
||||||
{
|
|
||||||
printf("南向:收到电桩 %d 上电指令\r\n", id);
|
|
||||||
local_on_cmd_callback_power_on(id, json_pack);
|
|
||||||
}
|
|
||||||
// 处理心跳指令
|
|
||||||
else if (strcmp(cmd, "heartbeat") == 0)
|
|
||||||
{
|
|
||||||
printf("南向:收到电桩 %d 心跳指令\r\n", id);
|
|
||||||
local_on_cmd_callback_heartbeat_response(id, json_pack);
|
|
||||||
}
|
|
||||||
// 处理实时数据指令
|
|
||||||
else if (strcmp(cmd, "realtime data") == 0)
|
|
||||||
{
|
|
||||||
printf("南向:收到电桩 %d 实时数据指令 \r\n", id);
|
|
||||||
local_on_cmd_callback_realtime_data_response(id, json_pack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*处理上位机指令 */
|
|
||||||
// 处理登录指令
|
|
||||||
else if (strcmp(cmd, "server_login") == 0)
|
|
||||||
{
|
|
||||||
printf("上位机:收到登录指令 \r\n");
|
|
||||||
local_on_cmd_callback_server_login_response(json_pack);
|
|
||||||
}
|
|
||||||
// 处理获取状态查询指令
|
|
||||||
else if (strcmp(cmd, "server_get_status") == 0)
|
|
||||||
{
|
|
||||||
printf("上位机:收到获取状态查询指令 \r\n");
|
|
||||||
local_on_cmd_callback_server_get_status_response(json_pack);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Unknown CMD: '%s' from ID %d\r\n", cmd, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将16字节的交易序列号转换为32位16进制字符串
|
|
||||||
* @param trade_serial 16字节数组
|
|
||||||
* @param output_str 输出缓冲区(至少33字节)
|
|
||||||
*/
|
|
||||||
void trade_serial_to_string(uint8_t *trade_serial, char *output_str)
|
|
||||||
{
|
|
||||||
if (trade_serial == NULL || output_str == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
sprintf(&output_str[i * 2], "%02X", trade_serial[i]);
|
|
||||||
}
|
|
||||||
output_str[32] = '\0';
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
#ifndef __CHARGERTASK_H
|
|
||||||
#define __CHARGERTASK_H
|
|
||||||
|
|
||||||
/* includes ----------------------------------------------------------------------------------------------*/
|
|
||||||
#include "global.h"
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/api.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
|
|
||||||
/* macro ------------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* struct ------------------------------------------------------------------------------------------------*/
|
|
||||||
// 定义UDP消息体
|
|
||||||
typedef struct {
|
|
||||||
ip4_addr_t src_ip; // 来源IP
|
|
||||||
uint16_t src_port; // 来源端口
|
|
||||||
uint16_t len; // 数据长度
|
|
||||||
char *data; // 数据指针(动态分配)
|
|
||||||
} UdpMsg_t;
|
|
||||||
|
|
||||||
|
|
||||||
//void Charger_Task_Init(void);
|
|
||||||
void handle_udp_downlink(uint8_t id, const char *cmd, cJSON *json_pack);
|
|
||||||
void local_on_cmd_send_start_charging(uint8_t stake_index,uint8_t gun_id);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __CHARGERTASK_H */
|
|
||||||
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* @file user\task\HeartBeatTask.c
|
|
||||||
* @author luhuaishuai
|
|
||||||
* @version v0.1
|
|
||||||
* @date 2026-1-12
|
|
||||||
* @brief Briefly describe the function of your function
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "YkcTask.h"
|
|
||||||
#include "ChargerTask.h"
|
|
||||||
#include "lwip/opt.h"
|
|
||||||
#include "lwip/api.h"
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @funNm : YkcTask_Function
|
|
||||||
* @brief : 云快充平台交互任务
|
|
||||||
* @param : argument
|
|
||||||
* @retval: void
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint8_t SETP = 0;
|
|
||||||
void YkcTask_Function(void const *argument)
|
|
||||||
{
|
|
||||||
init_chargers(); /* 初始化桩结构体*/
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); /* 等待桩通讯协议层完成*/
|
|
||||||
osDelay(5000);
|
|
||||||
// send_server_address_to_air724();
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
TaskRunTimeStat.YkcTask.threads_runtime = GetTask_RunTime(YkcTaskID);
|
|
||||||
TaskRunTimeStat.YkcTask.threads_counter = GetTask_Beatcnt(YkcTaskID);
|
|
||||||
TaskRunTimeStat.YkcTask.threads_freestack = Get_Free_Stack(YkcTaskID);
|
|
||||||
|
|
||||||
switch (SETP)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
// 等待桩上电
|
|
||||||
if (!g_charger_manager.charger_piles[1 - 1].is_udp_online)
|
|
||||||
{
|
|
||||||
uint8_t open_cmd[] = {0x55, 0xAA, 0x3, 0x01, 0x01, 0xAA, 0x55};
|
|
||||||
Air724_Message_Send(open_cmd, sizeof(open_cmd));
|
|
||||||
osDelay(3000);
|
|
||||||
SETP = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("网关:等待桩上电指令\r\n");
|
|
||||||
osDelay(1000);
|
|
||||||
SETP = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
// 云快充登录认证
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
if (!g_charger_manager.charger_piles[1 - 1].is_online)
|
|
||||||
{
|
|
||||||
charger_to_server_0X01(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SETP = 2;
|
|
||||||
charger_to_server_0X05(1,1);
|
|
||||||
}
|
|
||||||
osDelay(5000);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
// 云快充计费模型请求
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
if (!g_charger_manager.charger_piles[1 - 1].get_model)
|
|
||||||
|
|
||||||
|
|
||||||
charger_to_server_0X09(1); // 桩1计费模型请求
|
|
||||||
else
|
|
||||||
SETP = 3;
|
|
||||||
osDelay(3000);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
charger_to_server_0X13(1, 1); // 上传状态
|
|
||||||
// local_on_cmd_send_start_charging(1, 1);
|
|
||||||
osDelay(3000);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// osDelay(2000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 解析云快充平台下行数据
|
|
||||||
* @note 解析云快充平台下行数据,根据不同的帧类型调用相应的处理函数
|
|
||||||
* @param stake_mark 桩编号
|
|
||||||
* @param pack 指向SERVER_PACK结构体的指针,包含下行数据
|
|
||||||
*/
|
|
||||||
void handle_ykc_downlink(uint8_t stake_mark, SERVER_PACK *pack)
|
|
||||||
{
|
|
||||||
switch (pack->frame_type)
|
|
||||||
{
|
|
||||||
case FRAME_TYPE_0X02:
|
|
||||||
on_cmd_frame_type_0X02(stake_mark, pack);
|
|
||||||
break;
|
|
||||||
case FRAME_TYPE_0X04:
|
|
||||||
on_cmd_frame_type_0X04(stake_mark, pack);
|
|
||||||
break;
|
|
||||||
case FRAME_TYPE_0X06:
|
|
||||||
on_cmd_frame_type_0X06(stake_mark, pack);
|
|
||||||
break;
|
|
||||||
case FRAME_TYPE_0X0A:
|
|
||||||
on_cmd_frame_type_0X0A(stake_mark, pack);
|
|
||||||
break;
|
|
||||||
case FRAME_TYPE_0X58:
|
|
||||||
on_cmd_frame_type_0X58(stake_mark, pack);
|
|
||||||
break;
|
|
||||||
case FRAME_TYPE_0X34:
|
|
||||||
on_cmd_frame_type_0X34(stake_mark, pack);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
|
|
||||||
#ifndef __YKCTASK_H
|
|
||||||
#define __YKCTASK_H
|
|
||||||
|
|
||||||
/* includes ----------------------------------------------------------------------------------------------*/
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
void handle_ykc_downlink(uint8_t stake_mark, SERVER_PACK *pack);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __YKCTASK_H */
|
|
||||||
Reference in New Issue
Block a user