单OpenApi账号调用接口的每分钟请求数最大限制:50
本功能默认不开启,需与责任商务沟通开通
请务必使用设备商身份获取Token,仅设备商Token有权限使用本接口
当前阶段仅支持子设备(如逆变器)的DeviceID维度下发指令,暂不支持设备的SN维度,不支持采集器维度
DeviceID请通过设备列表接口获取
自定义指令 | ||||
---|---|---|---|---|
接口描述 | 支持通过OpenApi进行采集器指令的下发。 | |||
请求URL | https://api.solarmanpv.com/device/v1.0/upgrade | |||
请求方式 | post | |||
请求类型 | application/json | |||
返回类型 | / | |||
请求参数 | ||||
参数名 | 数据类型 | 参数类型 | 是否必填 | 描述说明 |
language | string | query | N | 语言类型,示例值:zh |
authorization | string | header | Y | accessToken,示例值:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9 |
callBackUrl | string | body | Y | 指令结果回调地址 ,示例值:https://www.solarman.cn/ 回调结果中的响应参数定义见下文 回调地址请求类型:POST 发送完指令后 ,前60秒每3秒请求一次指令结果,60秒之后每30秒请求一次指令结果,有指令结果后就发起回调, 回调方需要返回“SUCCESS”响应,否则会重新发起回调,超过 600s 仍然无法回调成功则丢弃,不再回调 注意:回调返回值为大写SUCCESS字符串,不需要返回json |
content | string | body | Y | 采集器指令内容 |
deviceId | string | body | Y | 设备在平台内的唯一标识 ,示例值:200124137 该ID为子设备(如逆变器)的device_id 该ID可通过设备列表获取 非子设备SN,非采集器SN,非采集器device_id |
timeoutSeconds | INT | body | N | 控制命令的超时时间,若超过该时间没有收到反馈结果则判定为指令失败。该时间默认600秒。 可自定义输入的范围为10-600秒 |
响应参数 | ||||
参数名 | 数据类型 | 描述说明 | ||
code | string | 信息码 ,示例值:10000 | ||
msg | string | 信息描述 ,示例值:success | ||
success | boolean | 是否成功 ,示例值:true | ||
requestId | string | 请求标识 ,示例值:1d6f6eca9bee4b6483d4af064b659eec | ||
collectionTime | string | 设备最新数据接收时间戳,示例值:1615900034 | ||
connectStatus | INT | 平台定义的设备通讯状态 0:离线 1:在线 | ||
orderId | string | 指令任务的ID | ||
示例 | ||||
请求参数 | { “deviceID”: “1800800121-Igen”, “timeoutSeconds”: 120, “callBackUrl”: “http://localhost:8019/device/v1.0/callback“, “content”: “0103001B0001F40D” } |
|||
返回值 | { “code”: null, “msg”: null, “success”: true, “requestId”: “311d34904f1841999f2f58b9b43f8719”, “collectionTime”: “1615900034”, “connectStatus”: 1, “orderId”: “19928812” } |
支持的指令
英臻采集器网络制式 | 功能 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
GPRS/4G | 子设备固件升级 | AT+SFTPUPURL= | 125.125.125.125:21 | username | password | / | file_path_name | 2 | CRC32 |
描述,蜂窝制式采集器,必须使用本指令进行升级 内容与内容之间以’,’逗号分割 |
固定内容,不可修改 | ip:端口 | ftp账号 | ftp密码 | 文件路径 | 文件名 | 固定内容,不可修改 | CRC32算法,见后文 | |
示例指令 | AT+SFTPUPURL=125.125.125.125:21,username,password,/,file_path_name,2,CRC32 | ||||||||
WIFI/ETH | 子设备固件升级 | AT+INVUPURL= | http://url.url/file_path_name/ | ||||||
描述,WIFI和ETH采集器,必须使用本指令进行升级 内容与内容之间以’,’逗号分割 |
固定内容 | 1. url地址 1. 必须以http://开头 1. url整体长度不得超过70个字符, 1. 必须是公网可访问,通过GET可以直接下载文件的地址 |
|||||||
示例指令 | AT+INVUPURL=http://url.url/file_path_name |
附录
CRC32算法
/*******************************************************************************
*Function Name: Get_Inverter_Version_CRC32
*Description:
*Input: start:
*Output:
*Returns:
*******************************************************************************/
cyg_uint32 Get_Inverter_Version_CRC32(cyg_uint32 start_address, cyg_uint32 file_len)
{
//U8 loop = 0;
cyg_uint16 index = 0;
cyg_uint32 temp = 0;
cyg_uint32 loop_i = 0;
cyg_uint32 loop_j = 0;
cyg_uint32 h_CRC = 0;
cyg_uint32 flash_startAddr = 0;
yz_up_mid_buf = hfmem_malloc(1024);
if( yz_up_mid_buf == NULL )
{
return 0;
}
memset(yz_up_mid_buf, 0, 1024);
flash_startAddr = start_address;
for(loop_i = 0, h_CRC = 0xFFFFFFFF, loop_j = 0; loop_i < file_len; loop_i++, loop_j++)
{
if(loop_j == 1024)
{
loop_j = 0;
memset((char*)yz_up_mid_buf, 0, 1024);
yz_flash_read(flash_startAddr, (unsigned char *)yz_up_mid_buf, 1024);
for(index = 0; index < 256; index++)
{
temp = yz_up_mid_buf[index * 4];
temp = (temp << 8) & 0xff00;
temp += yz_up_mid_buf[index * 4 + 1];
temp = (temp << 8) & 0xffff00;
temp += yz_up_mid_buf[index * 4 + 2];
temp = (temp << 8) & 0xffffff00;
temp += yz_up_mid_buf[index * 4 + 3];
h_CRC = CRC32(h_CRC, (cyg_uint32 *)&temp, 1);
}
flash_startAddr += 1024;
}
}
if(loop_j)
{
memset(yz_up_mid_buf, 0, 1024);
yz_flash_read(flash_startAddr, (unsigned char *)yz_up_mid_buf, loop_j);
for(index = 0; index < (loop_j / 4); index++)
{
temp = yz_up_mid_buf[index * 4];
temp = (temp << 8) & 0xff00;
temp += yz_up_mid_buf[index * 4 + 1];
temp = (temp << 8) & 0xffff00;
temp += yz_up_mid_buf[index * 4 + 2];
temp = (temp << 8) & 0xffffff00;
temp += yz_up_mid_buf[index * 4 + 3];
h_CRC = CRC32(h_CRC, (cyg_uint32 *)&temp, 1);
}
loop_i = loop_j % 4;
if(loop_i != 0)
{
if(loop_i == 1)
{
temp = yz_up_mid_buf[index * 4];
}
else if(loop_i == 2)
{
temp = yz_up_mid_buf[index * 4];
temp = (temp << 8) & 0xff00;
temp += yz_up_mid_buf[index * 4 + 1];
}
else if(loop_i == 3)
{
temp = yz_up_mid_buf[index * 4];
temp = (temp << 8) & 0xff00;
temp += yz_up_mid_buf[index * 4 + 1];
temp = (temp << 8) & 0xffff00;
temp += yz_up_mid_buf[index * 4 + 2];
}
h_CRC = CRC32(h_CRC, (cyg_uint32 *)&temp, 1);
}
}
hfmem_free(yz_up_mid_buf);
return h_CRC;
}
/*******************************************************************************
*Function Name: CRC32
*Description:
*Input:
*Output:
*Returns:
*******************************************************************************/
cyg_uint32 CRC32(cyg_uint32 uCurCRC, cyg_uint32 * pcData, cyg_uint32 dwSize)
{
cyg_uint32 bits;
cyg_uint32 xbit;
cyg_uint32 data;
cyg_uint32 uCRC = 0;
uCRC = uCurCRC;
while (dwSize--)
{
xbit = ((cyg_uint32)1 << 31);
data = *pcData++;
for (bits = 0; bits < 32; bits++)
{
if (uCRC & 0x80000000)
{
uCRC <<= 1;
uCRC ^= 0x04c11db7;
}
else
uCRC <<= 1;
if (data & xbit)
uCRC ^= 0x04c11db7;
xbit >>= 1;
}
}
return uCRC;
}
CURL示例
## 3.10 采集器指令
curl -X "POST" "https://api.solarmanpv.com/device/v1.0/upgrade?language=zh" \
-H 'Authorization: bearer eyJhbGxxxxxxxxxxxxxxxxxxxLm10000uxxxxxxxxxxxLm100uxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxuxxxxxxxxxxxLm100uxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxxxxxxLm100uxxxxxxxLm100uSChpu1eLPQ' \
-H 'Content-Type: application/json' \
-d $'{
"deviceId": "1234567890",
"content": "AT+INVUPURL=http://fw.net.com/f/abc.bin",
"timeoutSeconds": "600",
"callBackUrl": "http://call.back.com:3000/solarman/api/callback/Success"
}'
JAVA示例
import java.io.IOException;
import org.apache.http.client.fluent.*;
import org.apache.http.entity.ContentType;
public class SendRequest
{
public static void main(String[] args) {
sendRequest();
}
private static void sendRequest() {
// 3.10 采集器指令 (POST )
try {
// Create request
Content content = Request.Post("https://api.solarmanpv.com/device/v1.0/upgrade?language=zh")
// Add headers
.addHeader("Authorization", "bearer eyJhbGxxxxxxxxxxxxxxxxxxxLm10000uxxxxxxxxxxxLm100uxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxuxxxxxxxxxxxLm100uxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxLm100uxxxxxxxxxxxxxxxxLm100uxxxxxxxLm100uSChpu1eLPQ")
.addHeader("Content-Type", "application/json")
// Add body
.bodyString("{\"deviceId\": \"1234567890\",\"content\": \"AT+INVUPURL=http://fw.net.com/f/abc.bin\",\"timeoutSeconds\": \"600\",\"callBackUrl\": \"http://call.back.com:3000/solarman/api/callback/Success\"}", ContentType.APPLICATION_JSON)
// Fetch request and return content
.execute().returnContent();
// Print content
System.out.println(content);
}
catch (IOException e) { System.out.println(e); }
}
}