Energy data collection based on blockchain
Blockchain is a chain of blocks. Each block stores certain information, and they are connected into a chain in the order of their generation. This chain is stored in all servers. As long as there is one server in the entire system that can work, the entire blockchain is safe. These servers are called nodes in the blockchain system, and they provide storage space and computing power support for the entire blockchain system. If you want to modify the information in the blockchain, you must obtain the consent of more than half of the nodes and modify the information in all nodes. These nodes are usually in the hands of different entities, so it is extremely difficult to tamper with the information in the blockchain. Compared with traditional networks, blockchain has two core characteristics: one is that data is difficult to tamper with, and the other is decentralization. Based on these two characteristics, the information recorded in the blockchain is more authentic and reliable, which can help solve the problem of people's distrust.
This project uses Raspberry Pi 400 to collect power energy values, obtain data from the terminal, and upload the data to the fiscobcos chain for storage, ensuring that the collected data is at the original end, preventing data tampering, and providing later data traceability. At the same time, blockchain services and blockchain browsers are deployed to facilitate later data queries.
- System architecture diagram
- Terminal Design
The terminal communicates with the power collection concentrator via Ethernet. The communication uses TCP long connection. The Raspberry Pi establishes TCP service and the concentrator is connected as a client. The communication adopts the standard "State Grid 376.1-2013 Protocol.doc".
The Raspberry Pi terminal establishes three threads, which are used for TCP data sending, TCP data receiving and parsing, and blockchain on-chain services.
- Blockchain design
The blockchain design is divided into two parts: the blockchain server design and the blockchain terminal SDK design. The server uses the chain service built by the open source fiscobcos, uses 4 nodes, and writes blockchain smart contracts to save and query data. The terminal SDK uses the SDK of Molink, integrates the blockchain contract, and reports and queries data through the contract interface.
- Web front-end design
The blockchain browser visualizes the data in the blockchain and displays it in real time. It is convenient for users to obtain the information in the current blockchain in the form of web pages. The main functional modules of the blockchain browser are: group switching module, configuration module, and blockchain information display module. The blockchain backend uses nginx service and the front end uses the framework vue-cli.
Key features include:
(1) The main functions are blockchain overview, block viewing, transaction viewing, node configuration, and group switching.
(2) To support group switching, groups and nodes need to be configured.
(3) After uploading and compiling the contract to send the transaction, you can view the transaction inputs and event decoding data.
(4) Blockchain overview, view blocks, view transactions and node configuration pages, and execute a round of requests every 10 seconds.
Pictures of each part of the work
Raspberry Pi
Electricity Meter
Concentrator
Web display
word file
作品提交.docx
(11.7 KB, downloads: 8)
Raspberry Pi terminal code
Download link: https://download.eeworld.com.cn/detail/29447945/625213
/******************************************************************************
* Copyright (C) 2018-2021 aitos.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#include "HelloWorld.h"
#include "demo_fiscobcos_helloworld.h"
#include "EEcontract.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
/**
* macro used to select wallet type:
* - USE_ONETIME_WALLET : create a one-time wallet
* - USE_CREATE_PERSIST_WALLET : create a persist wallet
* - USE_LOAD_PERSIST_WALLET : load a persist wallet
*
* macro used to select private key format:
* - USE_PRIKEY_FORMAT_INTERNAL_GENERATION : key is internal generated
* - USE_PRIKEY_FORMAT_EXTERNAL_INJECTION_PKCS : key is pkcs format via external injection
* - USE_PRIKEY_FORMAT_EXTERNAL_INJECTION_NATIVE : key is native format via external injection
*/
/**
* PKCS format demo key. The original private key of 'pkcs_demoKey' is
* "78a42562c1d19843fd6f5a0f07de0206fdcf2a682c5e0a9a814019abb531da3a"
*/
const BCHAR *pkcs_demoKey = "-----BEGIN PRIVATE KEY-----\n"
"MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgz3wfbqBIV+8EOR49yA4x\n"
"4o6uVigkoU+WwaAKdQe2fZahRANCAAQpe8iOa9nDLr9r7/2aokClH7/Gqy7F+ep/\n"
"SOf94NvnLoQILdWeBzeCotF1BoJyrfnXiMSgDZYexSsFFgNz8dJx\n"
"-----END PRIVATE KEY-----\n";
/**
* native demo key
*/
const BCHAR *native_demoKey = "0xcf7c1f6ea04857ef04391e3dc80e31e28eae562824a14f96c1a00a7507b67d96";
/**
* test node url
*/
const BCHAR *demoUrl = "http://192.168.2.106:8545";
/**
* transfer recipient address
*/
const BCHAR *demoRecipientAddress = "0x56435c68406f0c937e128b6750b5abea22285e52";
float User_data = 0;
BoatFiscobcosWallet *g_fiscobcos_wallet_ptr;
#if defined(USE_ONETIME_WALLET)
__BOATSTATIC BOAT_RESULT fiscobcos_createOnetimeWallet()
{
BSINT32 index;
BoatFiscobcosWalletConfig wallet_config = {0};
BUINT8 binFormatKey[32] = {0};
(void)binFormatKey; //avoid warning
/* wallet_config value assignment */
#if defined(USE_PRIKEY_FORMAT_INTERNAL_GENERATION)
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> wallet format: internal generated.");
wallet_config.prikeyCtx_config.prikey_genMode = BOAT_WALLET_PRIKEY_GENMODE_INTERNAL_GENERATION;
wallet_config.prikeyCtx_config.prikey_type = BOAT_WALLET_PRIKEY_TYPE_SECP256K1;
#elif defined(USE_PRIKEY_FORMAT_EXTERNAL_INJECTION_PKCS)
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> wallet format: external injection[pkcs].");
wallet_config.prikeyCtx_config.prikey_genMode = BOAT_WALLET_PRIKEY_GENMODE_EXTERNAL_INJECTION;
wallet_config.prikeyCtx_config.prikey_format = BOAT_WALLET_PRIKEY_FORMAT_PKCS;
wallet_config.prikeyCtx_config.prikey_type = BOAT_WALLET_PRIKEY_TYPE_SECP256K1;
wallet_config.prikeyCtx_config.prikey_content.field_ptr = (BUINT8 *)pkcs_demoKey;
wallet_config.prikeyCtx_config.prikey_content.field_len = strlen(pkcs_demoKey) + 1; //length contain terminator
#elif defined(USE_PRIKEY_FORMAT_EXTERNAL_INJECTION_NATIVE)
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> wallet format: external injection[native].");
wallet_config.prikeyCtx_config.prikey_genMode = BOAT_WALLET_PRIKEY_GENMODE_EXTERNAL_INJECTION;
wallet_config.prikeyCtx_config.prikey_format = BOAT_WALLET_PRIKEY_FORMAT_NATIVE;
wallet_config.prikeyCtx_config.prikey_type = BOAT_WALLET_PRIKEY_TYPE_SECP256K1;
UtilityHexToBin(binFormatKey, 32, native_demoKey, TRIMBIN_TRIM_NO, BOAT_FALSE);
wallet_config.prikeyCtx_config.prikey_content.field_ptr = binFormatKey;
//UtilityHexToBin(wallet_config.prikeyCtx_config.prikey_content, 32, native_demoKey, TRIMBIN_TRIM_NO, BOAT_FALSE);
wallet_config.prikeyCtx_config.prikey_content.field_len = 32;
#else
/* default is internal generation */
wallet_config.prikeyCtx_config.prikey_genMode = BOAT_WALLET_PRIKEY_GENMODE_INTERNAL_GENERATION;
wallet_config.prikeyCtx_config.prikey_type = BOAT_WALLET_PRIKEY_TYPE_SECP256K1;
#endif
strncpy(wallet_config.node_url_str, demoUrl, BOAT_FISCOBCOS_NODE_URL_MAX_LEN - 1);
/* create fiscobcos wallet */
index = BoatWalletCreate(BOAT_PROTOCOL_FISCOBCOS, NULL, &wallet_config, sizeof(BoatFiscobcosWalletConfig));
if (index < 0)
{
//BoatLog(BOAT_LOG_CRITICAL, "create one-time wallet failed.");
return BOAT_ERROR_WALLET_CREATE_FAIL;
}
g_fiscobcos_wallet_ptr = BoatGetWalletByIndex(index);
return BOAT_SUCCESS;
}
#endif
#if defined(USE_CREATE_PERSIST_WALLET)
__BOATSTATIC BOAT_RESULT fiscobcos_createPersistWallet(BCHAR *wallet_name)
{
BSINT32 index;
BoatFiscobcosWalletConfig wallet_config = {0};
BUINT8 binFormatKey[32] = {0};
(void)binFormatKey; //avoid warning
/* wallet_config value assignment */
#if defined(USE_PRIKEY_FORMAT_INTERNAL_GENERATION)
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> wallet format: internal generated.");
wallet_config.prikeyCtx_config.prikey_genMode = BOAT_WALLET_PRIKEY_GENMODE_INTERNAL_GENERATION;
wallet_config.prikeyCtx_config.prikey_type = BOAT_WALLET_PRIKEY_TYPE_SECP256K1;
#elif defined(USE_PRIKEY_FORMAT_EXTERNAL_INJECTION_PKCS)
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> wallet format: external injection[pkcs].");
wallet_config.prikeyCtx_config.prikey_genMode = BOAT_WALLET_PRIKEY_GENMODE_EXTERNAL_INJECTION;
wallet_config.prikeyCtx_config.prikey_format = BOAT_WALLET_PRIKEY_FORMAT_PKCS;
wallet_config.prikeyCtx_config.prikey_type = BOAT_WALLET_PRIKEY_TYPE_SECP256K1;
wallet_config.prikeyCtx_config.prikey_content.field_ptr = (BUINT8 *)pkcs_demoKey;
wallet_config.prikeyCtx_config.prikey_content.field_len = strlen(pkcs_demoKey) + 1; //length contain terminator
#elif (defined USE_PRIKEY_FORMAT_EXTERNAL_INJECTION_NATIVE)
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> wallet format: external injection[native].");
wallet_config.prikeyCtx_config.prikey_genMode = BOAT_WALLET_PRIKEY_GENMODE_EXTERNAL_INJECTION;
wallet_config.prikeyCtx_config.prikey_format = BOAT_WALLET_PRIKEY_FORMAT_NATIVE;
wallet_config.prikeyCtx_config.prikey_type = BOAT_WALLET_PRIKEY_TYPE_SECP256K1;
UtilityHexToBin(binFormatKey, 32, native_demoKey, TRIMBIN_TRIM_NO, BOAT_FALSE);
wallet_config.prikeyCtx_config.prikey_content.field_ptr = binFormatKey;
wallet_config.prikeyCtx_config.prikey_content.field_len = 32;
#else
/* default is internal generation */
wallet_config.prikeyCtx_config.prikey_genMode = BOAT_WALLET_PRIKEY_GENMODE_INTERNAL_GENERATION;
wallet_config.prikeyCtx_config.prikey_type = BOAT_WALLET_PRIKEY_TYPE_SECP256K1;
#endif
strncpy(wallet_config.node_url_str, demoUrl, BOAT_FISCOBCOS_NODE_URL_MAX_LEN - 1);
/* create fiscobcos wallet */
index = BoatWalletCreate(BOAT_PROTOCOL_FISCOBCOS, wallet_name, &wallet_config, sizeof(BoatFiscobcosWalletConfig));
if (index < 0)
{
//BoatLog(BOAT_LOG_CRITICAL, "create persist wallet failed.");
return BOAT_ERROR_WALLET_CREATE_FAIL;
}
g_fiscobcos_wallet_ptr = BoatGetWalletByIndex(index);
return BOAT_SUCCESS;
}
#endif
#if defined(USE_LOAD_PERSIST_WALLET)
__BOATSTATIC BOAT_RESULT fiscobcos_loadPersistWallet(BCHAR *wallet_name)
{
BSINT32 index;
/* create fiscobcos wallet */
index = BoatWalletCreate(BOAT_PROTOCOL_FISCOBCOS, wallet_name, NULL, sizeof(BoatFiscobcosWalletConfig));
if (index < 0)
{
//BoatLog(BOAT_LOG_CRITICAL, "load wallet failed.");
return BOAT_ERROR_WALLET_CREATE_FAIL;
}
g_fiscobcos_wallet_ptr = BoatGetWalletByIndex(index);
return BOAT_SUCCESS;
}
#endif
BOAT_RESULT fiscobcos_helloworld(BoatFiscobcosWallet *wallet_ptr,BCHAR* dt,BCHAR* use,BCHAR*id,BCHAR*key)
{
BCHAR *result_str;
BoatFiscobcosTx tx_ctx;
BOAT_RESULT result;
/* Set Contract Address */
result = BoatFiscobcosTxInit(wallet_ptr, &tx_ctx, BOAT_TRUE,
"0x11E1A300", //gasprice
"0x33333333", //gaslimit
(BCHAR *)demoRecipientAddress, //recipient
"0x01", //chainid
"0x01" //groupid
);
if (result != BOAT_SUCCESS)
{
//BoatLog(BOAT_LOG_NORMAL, "BoatFiscobcosTxInit fails.");
return BOAT_ERROR_WALLET_INIT_FAIL;
}
result_str = EEcontract_saveDate(&tx_ctx, dt,use,id,key);
if (result_str == NULL)
{
//BoatLog(BOAT_LOG_NORMAL, "HelloWorld_set failed: %s.", result_str);
return BOAT_ERROR;
}
//BoatLog(BOAT_LOG_NORMAL, "set returns: %s", result_str);
result_str = EEcontract_getUseByIddt(&tx_ctx,key);
if (result_str == NULL)
{
//BoatLog(BOAT_LOG_NORMAL, "HelloWorld_get failed: %s.", result_str);
return BOAT_ERROR;
}
printf("test:%s\n",result_str);
//BoatLog(BOAT_LOG_NORMAL, "get returns: %s", result_str);
return BOAT_SUCCESS;
}
void fiscobcos_main(void)
{
BOAT_RESULT result = BOAT_SUCCESS;
boat_try_declare;
char data_time[128];
char use_data[128];
char user_id[128];
char key_data[128];
int cnt = 0;
time_t now;
struct tm *t;
/* step-1: Boat SDK initialization */
BoatIotSdkInit();
/* step-2: create fiscobcos wallet */
#if defined(USE_ONETIME_WALLET)
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> wallet type: create one-time wallet.");
result = fiscobcos_createOnetimeWallet();
#elif defined(USE_CREATE_PERSIST_WALLET)
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> wallet type: create persist wallet.");
result = fiscobcos_createPersistWallet("fiscobcos.cfg");
#elif defined(USE_LOAD_PERSIST_WALLET)
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> wallet type: load persist wallet.");
result = fiscobcos_loadPersistWallet("fiscobcos.cfg");
#else
//BoatLog(BOAT_LOG_NORMAL, ">>>>>>>>>> none wallet type selected.");
//return -1;
result = BOAT_ERROR;
#endif
if (result != BOAT_SUCCESS)
{
//BoatLog(BOAT_LOG_CRITICAL, "fiscobcosWalletPrepare_create failed : %d.", result);
//return -1;
boat_throw(result, fiscobcos_demo_catch);
}
while(1)
{
if(1)
{
time(&now);
t = localtime(&now);
memset(data_time,0,128);
sprintf(data_time,"%02d-%02d %02d:%02d:%02d",t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
memset(use_data,0,128);
sprintf(use_data,"%.2f",User_data);
memset(user_id,0,128);
sprintf(user_id,"SN0001");
memset(key_data,0,128);
sprintf(key_data,"key%d",cnt);
/* step-3: execute 'fiscobcos_call_helloworld' */
result = fiscobcos_helloworld(g_fiscobcos_wallet_ptr,(BCHAR*)data_time,(BCHAR*)use_data,(BCHAR*)user_id,(BCHAR*)key_data);
if (result != BOAT_SUCCESS)
{
//BoatLog(BOAT_LOG_NORMAL, "fiscobcos helloworld access Failed: %d.", result);
}
else
{
cnt ++;
//BoatLog(BOAT_LOG_NORMAL, "fiscobcos helloworld access Passed.");
}
boat_catch(fiscobcos_demo_catch)
{
}
}
sleep(30);
}
/* step-4: Boat SDK Deinitialization */
BoatIotSdkDeInit();
return 0;
}
//TCP服务器
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#define SERVPORT 8409
#define BACKLOG 10
#define MAXDATASIZE 1024
#define BUF_SIZE_MX 4096
unsigned char Recv_Buf[BUF_SIZE_MX];
KFIFO Tcp_recv_fifo;
GDW1376_1_STU gdw1376_1_data;
unsigned char datat_test2[] = { 0x68, 0x06, 0x01, 0x06, 0x01, 0x68, 0xA8, 0x90, 0x51, 0x9D, 0xE0, 0x00, 0x0C, 0x63, 0x00, 0x00, 0x01, 0x00, 0x5A, 0x4A, 0x57, 0x53, 0x5A, 0x4A, 0x57, 0x53, 0x44, 0x4A, 0x31, 0x33, 0x31, 0x36, 0x63, 0x33, 0x14, 0x06, 0x17, 0x46, 0x30, 0x36, 0x34, 0x52, 0x32, 0x35, 0x36, 0x4E, 0x31, 0x32, 0x31, 0x32, 0x47, 0x57, 0x56, 0x30, 0x2E, 0x38, 0x30, 0x08, 0x17, 0x00, 0x00, 0x02, 0x00, 0x31, 0x56, 0x09, 0x22, 0x89, 0x22, 0x14, 0x05, 0x66, 0x16 };
unsigned char data_test[] = { 0x68, 0x3A, 0x00, 0x3A, 0x00, 0x68, 0xE9, 0x90, 0x51, 0x9D, 0xE0, 0x00, 0x02, 0x7B, 0x00, 0x00, 0x01, 0x00, 0x0C, 0x05, 0xD6, 0x16 };
int GDW1376_1_protocol_parsing(unsigned char* pack_data, int len, GDW1376_1_STU* pro_stu);
void Function_link_Handle(unsigned char* buf, int len);
void Tcp_send_handle(void* pArg);
void printf_hex(unsigned char* data, int len)
{
int i = 0;
while (len--)
{
printf("%02x ", *data);
data++;
}
printf("\n");
/* for (i = 0; i < len; i ++);
{
printf("%d ",data);
}*/
}
char senddata[1024];
int sendlength = 0;
bool sendflag = false;
unsigned char sendindex = 0;
unsigned char g_seq = 0;
// void time_test()
// {
// time_t timep;
// time(&timep);
// char len[20] = { 0 };
// struct tm p;
// timep += 8 * 60 * 60;
// gmtime_s(&p,&timep);
// snprintf(len, 20, "%d-%d-%d %d:%d:%d", 1900 + p.tm_year, 1 + p.tm_mon, p.tm_mday, p.tm_hour, p.tm_min, p.tm_sec);
// printf("\n%s\n", len);
// }
int main() {
pthread_t id_recv,id_fiscobcos;
char revdata[MAXDATASIZE];
struct sockaddr_in server_sockaddr;//声明服务器socket存储结构
int sin_size,recvbytes;
int sockfd,client_fd;//socket描述符
char buf[MAXDATASIZE];//传输的数据
int ret;
//time_test();
Kfifo_Init(&Tcp_recv_fifo,Recv_Buf, BUF_SIZE_MX);
//1.建立socket
//AF_INET 表示IPV4
//SOCK_STREAM 表示TCP
if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
perror("Socket");
exit(1);
}
printf("Socket successful!,sockfd=%d\n",sockfd);
//以sockaddt_in结构体填充socket信息
server_sockaddr.sin_family = AF_INET;//IPv4
server_sockaddr.sin_port = htons(SERVPORT);//端口
server_sockaddr.sin_addr.s_addr = INADDR_ANY;//本主机的任意IP都可以使用
bzero(&(server_sockaddr.sin_zero),8);//保留的8字节置零
//2.绑定 fd与 端口和地址
if((bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr))) < 0) {
perror("bind");
exit(-1);
}
printf("bind successful !\n");
// //3.监听
if(listen(sockfd,BACKLOG) < 0) {
perror("listen");
exit(1);
}
printf("listening ... \n");
//4.接收请求,函数在有客户端连接时返回一个客户端socket fd,否则则阻塞
//优化:这里同样可以使用select,以及poll来实现异步通信
if((client_fd = accept(sockfd,NULL,&sin_size)) == -1) {
perror("accept");
exit(1);
}
printf("accept success! client_fd:%d\n",client_fd);
ret = pthread_create(&id_recv,NULL,Tcp_send_handle,(void *)&client_fd);
ret = pthread_create(&id_fiscobcos,NULL,fiscobcos_main,NULL);
while(1){
//5.接收数据
//注意:这里传入的fd,不是建立的socket fd,而是accept返回的连接客户端 socket fd
if((recvbytes = recv(client_fd,revdata,MAXDATASIZE,0)) == -1) {
perror("recv");
exit(1);
}
if( recvbytes >0 )
{
Kfifo_Put(&Tcp_recv_fifo,(unsigned char *)revdata,recvbytes);
/* revdata[ret] = 0x00;*/
printf("\n");
printf("客户端:");
printf_hex((unsigned char*)revdata, recvbytes);
GDW1376_1_protocol_parsing((unsigned char *)revdata, sizeof(revdata), &gdw1376_1_data);
printf("\n");
printf("received data : %s\n",buf);
}
sleep(1);
}
//6.关闭
close(sockfd);
}
unsigned int cmd_tabel[][2] = {
{0x0101,0x0401}, //查询电能
{0x0000,0x0002}, //查询时间
};
void Tcp_send_handle(void* pArg) {
int sClient;
unsigned int cnt = 0;
unsigned int test_DA = 0x0101;
unsigned int test_DT = 0x0401;
unsigned char test_DA1 = 0x00;
unsigned char test_DA2 = 0x00;
unsigned char test_DT1 = 0x00;
unsigned char test_DT2 = 0x00;
unsigned char test_cnt = 0;
sClient = *(int*)pArg;
while (1) {
cnt++;
if (cnt % 5 == 0)
{
if (sendflag == false)
{
/*if (test_DT2 >= 2 )
{
test_DA1 = 0xff;
test_DA2 = 0x00;
test_DA = test_DA1 | (test_DA2 << 8);
}
if (test_cnt >= 8)
{
test_cnt = 0;
test_DT1 = 0x01;
test_DT2 = test_DT2 + 1;
test_DT = test_DT1 | (test_DT2 << 8);
}
else
{
test_DT1 = ( 1 << test_cnt);
test_DT2 = test_DT2;
test_DT = test_DT1 | (test_DT2 << 8);
}*/
sendlength = GDW1376_1_get_terminal_time(g_seq,sendindex, test_DA, test_DT,(unsigned char *)senddata);
printf("服务端:");
printf_hex((unsigned char*)senddata, sendlength);
sendflag = true;
test_cnt++;
}
}
if (sendflag == true)
{
sendflag = false;
send(sClient, senddata, sendlength, 0);
sendindex++;
g_seq++;
}
if (sClient == NULL)
break;
sleep(1);
}
printf("send handle end\n");
}
//int main()
//{
// GDW1376_1_protocol_parsing(datat_test2,sizeof(datat_test2),&data);
//
// printf("pack len :%d\n",data.pack_len);
// std::cout << "Hello World!\n";
//
//}
unsigned char check_sum(unsigned char *data, int len)
{
unsigned char check = 0;
int i;
for (i = 0; i < len; i++)
{
check += data;
}
return check;
}
int GDW1376_1_protocol_parsing(unsigned char* pack_data, int len, GDW1376_1_STU* pro_stu)
{
bool result = false;
int index = 0;
int pack_len = 0;
unsigned int addr = 0;
unsigned char check = 0;
if (len < 14)
{
dbg_printf(" pack data len error!\n");
return result;
}
if (pack_data[index++] != PRO_HEAD)
{
dbg_printf(" pack data head error!\n");
return result;
}
pack_len |= pack_data[index];
index++;
pack_len |= (pack_data[index] << 8);
index++;
pack_len = 0;
pack_len |= pack_data[index];
index++;
pack_len |= (pack_data[index] << 8);
index++;
pro_stu->len.pro_len = pack_len;
if (pro_stu->len.len_stu.LEN_1 != PRO_VER_376_1)
{
dbg_printf(" pack pro ver error!(%d)\n", pro_stu->len.len_stu.LEN_1);
//return result;
}
pro_stu->pack_len = pro_stu->len.len_stu.LEN_L | (pro_stu->len.len_stu.LEN_H << 6);
pro_stu->user_data_len = pro_stu->pack_len - 6; //用户数据 + 控制域(1)+ 地址域(5) == 包长度
if (pack_data[index++] != PRO_HEAD)
{
dbg_printf(" pack data head error!\n");
//return result;
}
check = check_sum(&pack_data[index], pro_stu->user_data_len + 6);
if (check != pack_data[index + pro_stu->pack_len])
{
dbg_printf(" pack check error!(%d)\n", check);
//return result;
}
pro_stu->ctr.pro_ctr = pack_data[index++];
if (pro_stu->ctr.ctr_stu.CTR_DIR != PRO_DIR_UP)
{
dbg_printf(" pack DIR error!(%d)\n", pro_stu->ctr.ctr_stu.CTR_DIR);
//return result;
}
if (pro_stu->ctr.ctr_stu.CTR_PRM != PRO_PRM_1)
{
dbg_printf(" pack PRM error!(%d)\n", pro_stu->ctr.ctr_stu.CTR_PRM);
//return result;
}
addr = 0;
addr |= pack_data[index];
index++;
addr |= (pack_data[index] << 8);
index++;
pro_stu->pro_A1 = addr;
addr = 0;
addr |= pack_data[index];
index++;
addr |= (pack_data[index] << 8);
index++;
pro_stu->pro_A2 = addr;
pro_stu->pro_A3 = pack_data[index++];
pro_stu->user_data = (unsigned char*)malloc(pro_stu->user_data_len);
if (pro_stu->user_data == NULL)
{
dbg_printf(" user data malloc error!\n");
return result;
}
memcpy(pro_stu->user_data, &pack_data[index], pro_stu->user_data_len);
if (pro_stu->ctr.ctr_stu.CTR_PRM == 1)
{
switch (pro_stu->ctr.ctr_stu.CTR_FUN)
{
case PRO_FUN_REST:
dbg_printf("recv FUNCTION RESET\n");
break;
case PRO_FUN_USER:
dbg_printf("recv FUNCTION USER DATA\n");
break;
case PRO_FUN_LINK_TEST:
dbg_printf("recv FUNCTION LINK Test\n");
Function_link_Handle(pro_stu->user_data, pro_stu->user_data_len);
break;
case PRO_FUN_LEVEL1:
dbg_printf("recv FUNCTION LEVEL1\n");
break;
case PRO_FUN_LEVEL2:
dbg_printf("recv FUNCTION LEVEL2\n");
break;
default:
dbg_printf("recv FUNCTION unkown\n");
break;
}
}
else
{
switch (pro_stu->ctr.ctr_stu.CTR_FUN)
{
case PRO_FUN_OK:
dbg_printf("recv PRO_FUN_OK(PRM == 0)\n");
break;
case PRO_FUN_USER_ANS:
dbg_printf("recv PRO_FUN_USER_ANS(PRM == 0)\n");
Function_user_handle(pro_stu->user_data, pro_stu->user_data_len);
break;
case PRO_FUN_NO_ANS:
dbg_printf("recv PRO_FUN_NO_ANS(PRM == 0)\n");
break;
case PRO_FUN_LINK_STA:
dbg_printf("recv PRO_FUN_LINK_STA(PRM == 0)\n");
break;
default:
break;
}
}
if (pro_stu->user_data != NULL)
{
free(pro_stu->user_data);
}
result = true;
return result;
}
void Function_user_handle(unsigned char* buf, int len)
{
unsigned char afn_value = 0;
int index = 0;
APP_SEQ_UNION app_seq;
unsigned int app_DA = 0;
unsigned int app_DT = 0;
unsigned char year = 0;
unsigned char mon = 0;
unsigned char day = 0;
unsigned char hour = 0;
unsigned char min = 0;
unsigned char cnt = 0;
float Power_F;
float Power_I;
afn_value = buf[index];
index++;
app_seq.app_seq = buf[index];
index++;
app_DA = buf[index];
index++;
app_DA |= (buf[index] << 8);
index++;
app_DT = buf[index];
index++;
app_DT |= (buf[index] << 8);
index++;
switch (afn_value)
{
case AFN_GET_1:
dbg_printf("recv AFN_GET_1\n");
if (app_DA == 0x0101 && app_DT == 0x0401) //F33 当前正向有/无功(组合无功1)电能示值、一/四象限无功电能示值(总、费率1~M,1≤M≤12)
{
year = buf[index++];
mon = buf[index++];
day = buf[index++];
hour = buf[index++];
min = buf[index++];
cnt = buf[index++];
Power_F = 0;
Power_I = 0;
Power_F += ( Bcd2Bin(buf[index]) / 10000);
index++;
Power_F += ((float)Bcd2Bin(buf[index]) / 100);
index++;
Power_I += (Bcd2Bin(buf[index]) );
index++;
Power_I += (Bcd2Bin(buf[index]) * 100);
index++;
Power_I += (Bcd2Bin(buf[index]) * 10000);
index++;
User_data = Power_I + Power_F;
dbg_printf(" get power:%f kWh\n",User_data );
}
break;
default:
break;
}
}
void Function_link_Handle(unsigned char* buf, int len)
{
unsigned char afn_value = 0;
int index = 0;
APP_SEQ_UNION app_seq;
unsigned int app_DA = 0;
unsigned int app_DT = 0;
int length = 0;
afn_value = buf[index];
index++;
app_seq.app_seq = buf[index];
index++;
app_DA = buf[index];
index++;
app_DA |= ( buf[index] << 8 );
index++;
app_DT = buf[index];
index++;
app_DT |= (buf[index] << 8);
index++;
switch (afn_value)
{
case AFN_ANS:
dbg_printf("recv AFN_ANS\n");
break;
case AFN_REST:
dbg_printf("recv AFN_REST\n");
break;
case AFN_LINK_TEST:
dbg_printf("recv AFN_LINK_TEST\n");
if (app_DA == 0 && app_DT == 1)
{
dbg_printf("recv LINK TEST login\n");
while (sendflag == true);
g_seq = app_seq.seq_stu.SEQ_NO;
memset(senddata, 0, 1024);
length = GDW1376_1_pack_login_ans(app_seq.seq_stu.SEQ_NO, app_DA, app_DT, (unsigned char *)senddata);
printf("服务端:");
printf_hex((unsigned char *)senddata, length);
sendlength = length;
sendflag = true;
/*send(sClient, senddata, length, 0);*/
}
if (app_DA == 0 && app_DT == 2)
{
dbg_printf("recv LINK TEST logout\n");
}
if (app_DA == 0 && app_DT == 4)
{
dbg_printf("recv LINK TEST heart\n");
while (sendflag == true);
g_seq = app_seq.seq_stu.SEQ_NO;
memset(senddata, 0, 1024);
length = GDW1376_1_pack_heart_ans(afn_value,app_seq.seq_stu.SEQ_NO, app_DA, app_DT, (unsigned char*)senddata);
printf("服务端:");
printf_hex((unsigned char*)senddata, length);
sendlength = length;
sendflag = true;
/*send(sClient, senddata, length, 0);*/
}
break;
case AFN_RELAY_CMD:
dbg_printf("recv AFN_RELAY_CMD\n");
break;
case AFN_SET:
dbg_printf("recv AFN_SET\n");
break;
case AFN_CONTROL:
dbg_printf("recv AFN_CONTROL\n");
break;
case AFN_RES:
dbg_printf("recv AFN_RES\n");
break;
case AFN_AUTO_UP:
dbg_printf("recv AFN_AUTO_UP\n");
break;
case AFN_TER_CONF:
dbg_printf("recv AFN_TER_CONF\n");
break;
case AFN_QUERY:
dbg_printf("recv AFN_QUERY\n");
break;
case AFN_GET_1:
dbg_printf("recv AFN_GET_1\n");
break;
case AFN_GET_2:
dbg_printf("recv AFN_GET_2\n");
break;
case AFN_GET_3:
dbg_printf("recv AFN_GET_3\n");
break;
case AFN_FILE:
dbg_printf("recv AFN_FILE\n");
break;
case AFN_DATA_FORWARD:
dbg_printf("recv AFN_DATA_FORWARD\n");
break;
default:
dbg_printf("recv AFN_unkown\n");
break;
}
}
int GDW1376_1_package_get(unsigned char* buf,int len)
{
int index = 0;
buf[index++] = PRO_HEAD;
return 2;
}
int GDW1376_1_pack_login_ans(unsigned char seq, unsigned int app_DA, unsigned int app_DT,unsigned char *buf)
{
int index = 0;
unsigned char check = 0;
PRO_CTR_UNION pro_ctr;
APP_SEQ_UNION app_seq;
PRO_LEN_UNION pro_len;
pro_ctr.ctr_stu.CTR_FUN = PRO_FUN_LINK_TEST;
pro_ctr.ctr_stu.CTR_DIR = PRO_DIR_DOWN;
pro_ctr.ctr_stu.CTR_PRM = PRO_PRM_0;
pro_ctr.ctr_stu.CTR_FCB = PRO_FCB_0;
pro_ctr.ctr_stu.CTR_FCV = PRO_FCV_0;
app_seq.seq_stu.SEQ_NO = seq;
app_seq.seq_stu.SEQ_FIN = 1;
app_seq.seq_stu.SEQ_FIR = 1;
app_seq.seq_stu.SEQ_TpV = 0;
app_seq.seq_stu.SEQ_CON = 0;
buf[index++] = PRO_HEAD;
buf[index++] = 0x00;
buf[index++] = 0x00;
buf[index++] = 0x00;
buf[index++] = 0x00;
buf[index++] = PRO_HEAD;
buf[index++] = pro_ctr.pro_ctr;
buf[index++] = gdw1376_1_data.pro_A1 & 0xff;
buf[index++] = ( gdw1376_1_data.pro_A1 >> 8) & 0xff;
buf[index++] = gdw1376_1_data.pro_A2 & 0xff;
buf[index++] = (gdw1376_1_data.pro_A2 >> 8) & 0xff;
buf[index++] = gdw1376_1_data.pro_A3;
buf[index++] = AFN_ANS;
buf[index++] = app_seq.app_seq;
buf[index++] = app_DA & 0xff;
buf[index++] = (app_DA >> 8) & 0xff;
buf[index++] = app_DT & 0xff;
buf[index++] = (app_DT >> 8) & 0xff;
check = check_sum(&buf[6], index - 6);
pro_len.len_stu.LEN_1 = PRO_VER_376_1;
pro_len.len_stu.LEN_L = (index - 6) & 0x3f;
pro_len.len_stu.LEN_H = ((index - 6) >> 6) & 0xff;
buf[1] = pro_len.pro_len & 0xff;
buf[2] = (pro_len.pro_len >> 8) & 0xff;
buf[3] = pro_len.pro_len & 0xff;
buf[4] = (pro_len.pro_len >> 8) & 0xff;
buf[index++] = check;
buf[index++] = PRO_TAIL;
return index;
}
int GDW1376_1_pack_heart_ans(unsigned char afn,unsigned char seq, unsigned int app_DA, unsigned int app_DT, unsigned char* buf)
{
int index = 0;
unsigned char check = 0;
unsigned int DA = 0x00;
unsigned int DT = 0x04;
PRO_CTR_UNION pro_ctr;
APP_SEQ_UNION app_seq;
PRO_LEN_UNION pro_len;
pro_ctr.ctr_stu.CTR_FUN = PRO_FUN_LINK_TEST;
pro_ctr.ctr_stu.CTR_DIR = PRO_DIR_DOWN;
pro_ctr.ctr_stu.CTR_PRM = PRO_PRM_0;
pro_ctr.ctr_stu.CTR_FCB = PRO_FCB_0;
pro_ctr.ctr_stu.CTR_FCV = PRO_FCV_0;
app_seq.seq_stu.SEQ_NO = seq;
app_seq.seq_stu.SEQ_FIN = 1;
app_seq.seq_stu.SEQ_FIR = 1;
app_seq.seq_stu.SEQ_TpV = 0;
app_seq.seq_stu.SEQ_CON = 0;
buf[index++] = PRO_HEAD;
buf[index++] = 0x00;
buf[index++] = 0x00;
buf[index++] = 0x00;
buf[index++] = 0x00;
buf[index++] = PRO_HEAD;
buf[index++] = pro_ctr.pro_ctr;
buf[index++] = gdw1376_1_data.pro_A1 & 0xff;
buf[index++] = (gdw1376_1_data.pro_A1 >> 8) & 0xff;
buf[index++] = gdw1376_1_data.pro_A2 & 0xff;
buf[index++] = (gdw1376_1_data.pro_A2 >> 8) & 0xff;
buf[index++] = gdw1376_1_data.pro_A3;
buf[index++] = AFN_ANS;
buf[index++] = app_seq.app_seq;
buf[index++] = DA & 0xff;
buf[index++] = (DA >> 8) & 0xff;
buf[index++] = DT & 0xff;
buf[index++] = (DT >> 8) & 0xff;
buf[index++] = afn;
buf[index++] = app_DA & 0xff;
buf[index++] = (app_DA >> 8) & 0xff;
buf[index++] = app_DT & 0xff;
buf[index++] = (app_DT >> 8) & 0xff;
buf[index++] = ERR_OK;
check = check_sum(&buf[6], index - 6);
pro_len.len_stu.LEN_1 = PRO_VER_376_1;
pro_len.len_stu.LEN_L = (index - 6) & 0x3f;
pro_len.len_stu.LEN_H = ((index - 6) >> 6) & 0xff;
buf[1] = pro_len.pro_len & 0xff;
buf[2] = (pro_len.pro_len >> 8) & 0xff;
buf[3] = pro_len.pro_len & 0xff;
buf[4] = (pro_len.pro_len >> 8) & 0xff;
buf[index++] = check;
buf[index++] = PRO_TAIL;
return index;
}
int GDW1376_1_get_terminal_time(unsigned char seq,unsigned char send_index, unsigned int DA,unsigned int DT,unsigned char* buf)
{
int index = 0;
unsigned char check = 0;
//unsigned int DA = 0x00;
//unsigned int DT = 0x02;
PRO_CTR_UNION pro_ctr;
APP_SEQ_UNION app_seq;
PRO_LEN_UNION pro_len;
struct tm *t;
time_t timep;
time(&timep);
timep += 8 * 60 * 60;
t = localtime(&timep);
pro_ctr.ctr_stu.CTR_FUN = PRO_FUN_LEVEL2;
pro_ctr.ctr_stu.CTR_DIR = PRO_DIR_DOWN;
pro_ctr.ctr_stu.CTR_PRM = PRO_PRM_1;
pro_ctr.ctr_stu.CTR_FCB = PRO_FCB_0;
pro_ctr.ctr_stu.CTR_FCV = PRO_FCV_0;
app_seq.seq_stu.SEQ_NO = seq;
app_seq.seq_stu.SEQ_FIN = 1;
app_seq.seq_stu.SEQ_FIR = 1;
app_seq.seq_stu.SEQ_TpV = 0;
app_seq.seq_stu.SEQ_CON = 1;
buf[index++] = PRO_HEAD;
buf[index++] = 0x00;
buf[index++] = 0x00;
buf[index++] = 0x00;
buf[index++] = 0x00;
buf[index++] = PRO_HEAD;
buf[index++] = pro_ctr.pro_ctr;
buf[index++] = gdw1376_1_data.pro_A1 & 0xff;
buf[index++] = (gdw1376_1_data.pro_A1 >> 8) & 0xff;
buf[index++] = gdw1376_1_data.pro_A2 & 0xff;
buf[index++] = (gdw1376_1_data.pro_A2 >> 8) & 0xff;
buf[index++] = gdw1376_1_data.pro_A3;
buf[index++] = AFN_GET_1;
buf[index++] = app_seq.app_seq;
buf[index++] = DA & 0xff;
buf[index++] = (DA >> 8) & 0xff;
buf[index++] = DT & 0xff;
buf[index++] = (DT >> 8) & 0xff;
buf[index++] = send_index;
buf[index++] = Hex2Bcd(t->tm_sec);
buf[index++] = Hex2Bcd(t->tm_min);
buf[index++] = Hex2Bcd(t->tm_hour);
buf[index++] = Hex2Bcd(t->tm_mday);
/*buf[index++] = Hex2Bcd(p.tm_mon);
buf[index++] = Hex2Bcd(p.tm_year+1900);*/
buf[index++] = TIME_OUT_MX;
check = check_sum(&buf[6], index - 6);
pro_len.len_stu.LEN_1 = PRO_VER_376_1;
pro_len.len_stu.LEN_L = (index - 6) & 0x3f;
pro_len.len_stu.LEN_H = ((index - 6) >> 6) & 0xff;
buf[1] = pro_len.pro_len & 0xff;
buf[2] = (pro_len.pro_len >> 8) & 0xff;
buf[3] = pro_len.pro_len & 0xff;
buf[4] = (pro_len.pro_len >> 8) & 0xff;
buf[index++] = check;
buf[index++] = PRO_TAIL;
return index;
}
unsigned char Hex2Bcd(unsigned char HexCode)
{
return((HexCode % 10) + (HexCode / 10 * 16));
}
unsigned char Bcd2Bin(unsigned char BcdCode)
{
return((((BcdCode >> 4) & 0x0F) * 10) + (BcdCode & 0x0F));
}
void Kfifo_Init(KFIFO* fifo, unsigned char* buffer, unsigned int size)
{
fifo->buffer = buffer;
fifo->size = size;
fifo->in = 0;
fifo->out = 0;
}
unsigned int Kfifo_Put(KFIFO* fifo, unsigned char* buffer, unsigned int len)
{
unsigned int l;
len = min(len, (fifo->size + fifo->out - fifo->in));
/*
* Ensure that we sample the fifo->out index -before- we
* start putting bytes into the kfifo.
*/
/* first put the data starting from fifo->in to buffer end */
l = min(len, (fifo->size - (fifo->in & (fifo->size - 1))));
memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
/* then put the rest (if any) at the beginning of the buffer */
memcpy(fifo->buffer, buffer + l, len - l);
/*
* Ensure that we add the bytes to the kfifo -before-
* we update the fifo->in index.
*/
fifo->in += len;
return len;
}
unsigned int Kfifo_Get(KFIFO* fifo, unsigned char* buffer, unsigned int len)
{
unsigned int l;
len = min(len, (fifo->in - fifo->out));
/*
* Ensure that we sample the fifo->in index -before- we
* start removing bytes from the kfifo.
*/
/* first get the data from fifo->out until the end of the buffer */
l = min(len, (fifo->size - (fifo->out & (fifo->size - 1))));
memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
/* then get the rest (if any) from the beginning of the buffer */
memcpy(buffer + l, fifo->buffer, len - l);
/*
* Ensure that we remove the bytes from the kfifo -before-
* we update the fifo->out index.
*/
fifo->out += len;
return len;
}
unsigned int Kfifo_Get_len(KFIFO* fifo)
{
unsigned int l;
if (fifo->in >= fifo->out)
l = fifo->in - fifo->out;
else
l = fifo->size - fifo->out + fifo->in;
return l;
}
unsigned int Kfifo_Get_free_len(KFIFO* fifo)
{
unsigned int l;
if (fifo->in >= fifo->out)
l = fifo->size - (fifo->in - fifo->out);
else
l = fifo->out - fifo->in;
return l;
}
int Kfifo_is_in(KFIFO* fifo)
{
int flag = 0;
static unsigned int inold;
if (inold != fifo->in)
{
inold = fifo->in;
flag = 1;
}
else
{
flag = 0;
}
return flag;
}
Blockchain server deployment script
sudo apt install -y openssl curl
cd ~ && mkdir -p fisco && cd fisco
curl -#LO https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.9.1/build_chain.sh && chmod u+x build_chain.sh
bash build_chain.sh -l 127.0.0.1:4 -p 30300,20200,8545
bash nodes/127.0.0.1/start_all.sh
ps -ef | grep -v grep | grep fisco-bcos
tail -f nodes/127.0.0.1/node0/log/log* | grep connected
cd ~/fisco && curl -LO https://github.com/FISCO-BCOS/console/releases/download/v2.9.1/download_console.sh && bash download_console.sh
cp -n console/conf/config-example.toml console/conf/config.toml
cp -r nodes/127.0.0.1/sdk/* console/conf/
cd ~/fisco/console && bash start.sh
deploy EEcontract
Deploy some scripts of blockchain browser
git clone https://github.com/FISCO-BCOS/fisco-bcos-browser.git
cd server/fisco-bcos-browser
gradle build
mysql -u ${your_db_account} -p${your_db_password} 例如:mysql -u root -p123456
CREATE DATABASE IF NOT EXISTS {your_db_name} DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
cd dist/script
修改数据库名称:sed -i "s/db_browser/${your_db_name}/g" browser.sh
修改数据库用户名:sed -i "s/dbUsername/${your_db_account}/g" browser.sh
修改数据库密码:sed -i "s/dbPassword/${your_db_password}/g" browser.sh
sed -i "s/dbUsername/root/g" browser.sh
bash browser.sh 127.0.0.1 3306
cd dist/conf
修改当前服务端口:sed -i "s/5101/${your_server_port}/g" application.yml
修改数据库IP:sed -i "s/127.0.0.1/${your_db_ip}/g" application.yml
修改数据库用户名:sed -i "s/dbUsername/${your_db_account}/g" application.yml
修改数据库密码:sed -i "s/dbPassword/${your_db_password}/g" application.yml
修改数据库名称:sed -i "s/db_browser/${your_db_name}/g" application.yml
cd dist
启动:sh start.sh
停止:sh stop.sh
检查:sh status.
Demo Video
|