在上一篇博客中我使用智能涡轮流量计采集了一些数据上传到Hyperledger的链码上,此前对链码的一些数据结构进行了修改,但是还存在一些小问题。

https://blog.csdn.net/qq_43824745/article/details/125876812?spm=1001.2014.3001.5501

此前的test链码如下:

/*
SPDX-License-Identifier: Apache-2.0
*/package mainimport ("encoding/json""fmt""github.com/hyperledger/fabric-contract-api-go/contractapi"
)type SmartContract struct {contractapi.Contract
}type Data struct {Now  string `json:"now(L/H)"`Total   string `json:"total(L)"`
}type QueryResult struct {Key    string `json:"Key"`Record *Data
}func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {datas := []Data{Data{Now:"0", Total: "0"},}for data := range datas {dataAsBytes, _ := json.Marshal(data)err := ctx.GetStub().PutState("2022-07-20 00:00", dataAsBytes)if err != nil {return fmt.Errorf("Failed to put to world state. %s", err.Error())}}return nil
}func (s *SmartContract) AddData(ctx contractapi.TransactionContextInterface, dataNumber string, now string, total string) error {data := Data{Now:    now,Total:   total,}dataAsBytes, _ := json.Marshal(data)return ctx.GetStub().PutState(dataNumber, dataAsBytes)
}func (s *SmartContract) QueryData(ctx contractapi.TransactionContextInterface, dataNumber string) (*Data, error) {dataAsBytes, err := ctx.GetStub().GetState(dataNumber)if err != nil {return nil, fmt.Errorf("Failed to read from world state. %s", err.Error())}if dataAsBytes == nil {return nil, fmt.Errorf("%s does not exist", dataNumber)}data := new(Data)_ = json.Unmarshal(dataAsBytes, data)return data, nil
}func (s *SmartContract) QueryAllDatas(ctx contractapi.TransactionContextInterface) ([]QueryResult, error) {startKey := ""endKey := ""resultsIterator, err := ctx.GetStub().GetStateByRange(startKey, endKey)if err != nil {return nil, err}defer resultsIterator.Close()results := []QueryResult{}for resultsIterator.HasNext() {queryResponse, err := resultsIterator.Next()if err != nil {return nil, err}data := new(Data)_ = json.Unmarshal(queryResponse.Value, data)queryResult := QueryResult{Key: queryResponse.Key, Record: data}results = append(results, queryResult)}return results, nil
}func main() {chaincode, err := contractapi.NewChaincode(new(SmartContract))if err != nil {fmt.Printf("Error create test chaincode: %s", err.Error())return}if err := chaincode.Start(); err != nil {fmt.Printf("Error starting test chaincode: %s", err.Error())}
}

可以看到我将采集数据的时间精确到分钟的形式作为Data的Key,这样操作的好处是查询所有数据时不会出现Key按字典序排列时产生乱序的现象,结果如下:

每条查询结果均按时间顺序排列,看起来很合理,但是这样处理在查询单条数据时会有不便,因为单条数据查询时需要指定要查询的数据所对应的Key,而上述的Key值是精确到分钟的时间形式,而用户不可能清楚每条记录都是在具体哪一分钟上传的,所以我设想将Key中的时间调整为日期的形式,再对这一天的每一条数据进行编号,为了不产生字典序排列混乱,我准备用定长的数字ID进行编号。

考虑到脚本运行间隔是5分钟,一天能产生的数据总量为不到300条,所以用三位ID来编号是足够的,比如Key为“2022-07-27 010”,其含义就是2022年7月27日这天的第10条数据,这样设计我认为对于用户查询单条数据这一需求算是比较合理的实现吧。由于编号只是对应于当天的编号,到第二天就需要重新从“001”开始计数,所以在脚本为每条数据编写Key值时需要判断一下此条数据是否属于当天,是则ID累加,否则ID归1。

修改后的test.go和shell脚本如下:

test.go:

/*
SPDX-License-Identifier: Apache-2.0
*/package mainimport ("encoding/json""fmt""github.com/hyperledger/fabric-contract-api-go/contractapi"
)type SmartContract struct {contractapi.Contract
}type Data struct {Now  string `json:"now(L/H)"`Total   string `json:"total(L)"`Time    string  `json:"time"`
}type QueryResult struct {Key    string `json:"Key"`Record *Data
}func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {datas := []Data{Data{Now:"0", Total: "0",Time:"12:00"},}for data := range datas {dataAsBytes, _ := json.Marshal(data)err := ctx.GetStub().PutState("2022-07-20 000", dataAsBytes)if err != nil {return fmt.Errorf("Failed to put to world state. %s", err.Error())}}return nil
}func (s *SmartContract) AddData(ctx contractapi.TransactionContextInterface, dataNumber string, now string, total string,time string) error {data := Data{Now:    now,Total:   total,Time:    time,}dataAsBytes, _ := json.Marshal(data)return ctx.GetStub().PutState(dataNumber, dataAsBytes)
}func (s *SmartContract) QueryData(ctx contractapi.TransactionContextInterface, dataNumber string) (*Data, error) {dataAsBytes, err := ctx.GetStub().GetState(dataNumber)if err != nil {return nil, fmt.Errorf("Failed to read from world state. %s", err.Error())}if dataAsBytes == nil {return nil, fmt.Errorf("%s does not exist", dataNumber)}data := new(Data)_ = json.Unmarshal(dataAsBytes, data)return data, nil
}func (s *SmartContract) QueryAllDatas(ctx contractapi.TransactionContextInterface) ([]QueryResult, error) {startKey := ""endKey := ""resultsIterator, err := ctx.GetStub().GetStateByRange(startKey, endKey)if err != nil {return nil, err}defer resultsIterator.Close()results := []QueryResult{}for resultsIterator.HasNext() {queryResponse, err := resultsIterator.Next()if err != nil {return nil, err}data := new(Data)_ = json.Unmarshal(queryResponse.Value, data)queryResult := QueryResult{Key: queryResponse.Key, Record: data}results = append(results, queryResult)}return results, nil
}func main() {chaincode, err := contractapi.NewChaincode(new(SmartContract))if err != nil {fmt.Printf("Error create test chaincode: %s", err.Error())return}if err := chaincode.Start(); err != nil {fmt.Printf("Error starting test chaincode: %s", err.Error())}
}

脚本(没有用真实数据,只用随机数测试了一下):

#!/bin/bash
pre=$(date "+%Y-%m-%d")    //pre记录上一条数据的采集时间
num="1"                    //num记录当前数据是这一天的第几条数据
for i in {1..20}
do
#   sudo python /home/pi/RS485_CAN_HAT_Code/485/python/query_now.pynow=$(date "+%Y-%m-%d")if [ $pre != $now ]thennum="1"pre=$nowfiid=$numlen=${#id}while [ $len -le 2 ]doid="0"$idlet len+=1donelet num+=1time=$(date "+%H:%M")res=$now" "$id
#   sleep 3
#   echo " " >> data.txt
#   while read rows
#   do
#       n=$rows
#       break
#   done < data.txt
#   sudo python /home/pi/RS485_CAN_HAT_Code/485/python/query_total.py
#   sleep 3
#   echo " " >> data.txt
#   while read rows
#   do
#       t=$rows
#       break
#   done < data.txtn=$RANDOMt=$RANDOMecho "这是第"$i"次查询到并添加的数据:"echo "Now(L/H):"$n" Total(L):"$t" Time:"$timecmd="'{\"Args\":[\"AddData\",\"$res\",\"$n\",\"$t\",\"$time\"]}'"echo "Add命令:"$cmdecho "#!/bin/bash
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n newtest --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c "$cmd "
exit"> add.sh docker cp add.sh cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/docker exec -it cli bash add.shsleep 60
#break
done

脚本运行结果:

Org1查询所有数据结果:

Org1查询单条数据结果:

Hyperledger Fabric链码修改与测试(一)相关推荐

  1. HyperLedger Fabric链码开发及测试

    HyperLedger Fabric链码开发及测试 1.链码开发 先设计一个简单的应用场景,假设有这样的业务需求: 可以添加学校,信息包括学校名称.学校ID: 添加该学校的学生,信息包括姓名,用户ID ...

  2. hyperledger fabric 2.3.3 测试网络

    教程 一.注意事项 确保通道名称应用以下限制: 仅包含小写 ASCII 字母数字.点"."和破折号"-" 少于 250 个字符 以字母开头 二.hyperled ...

  3. Hyperledger Fabric 链码(0) 说明

    1. 概念 基于区块链的应用,一般都由部署在区块链上的智能合约以及调用这些智能合约的业务程序组成,智能合约又称为链码(Chaincode),是一段运行在容器中的程序. Chaincode 是客户端程序 ...

  4. Hyperledger Fabric 链码(2) 接口

    1.Chaincode interface:每个链码程序必须实现链码接口,用以响应接收的事务. 1.1 go语言的"shim "包中,接口规范如下: Init:在链码实例化或者升级 ...

  5. Hyperledger Fabric 链码(1) 类型

    1. 用户链码 由应用开发人员编写(Go/Java/JS语言) 基于区块链分布式账本的状态及处理逻辑运行在链码容器中, 通过Fabric提供的接口与账本平台进行交互. 2. 系统链码(ESCC) 负责 ...

  6. Hyperledger Fabric 链码(3) 生命周期和API

    1. Chaincode的5个生命周期命令 链码打包 链码安装 eg.peer chaincode install ccpack.out 链码实例化 eg. peer.sh chaincode ins ...

  7. fabric 启动peer_编写 Fabric 链码的一般准则

    我相信智能合约(链码)是 Hyperledger Fabric 区块链网络的核心.正确开发链码可以真正发挥一个安全区块链的优势,反之则会带来灾难性的后果.在这篇文章里我不打算探讨 Hyperledge ...

  8. Hyperledger Fabric 核心模块(2)configtxgen工具

    1. 说明 专门负责生成系统的创始块和通道Channel的创始块 . order 模块的genesis block创始块 channel 模块的 channel configuration trans ...

  9. Ubuntu 18.04上进行HyperLedger Fabric 1.2.0环境及链码安装、部署和测试

    Ubuntu 18.04上进行HyperLedger Fabric 1.2.0环境及链码安装.部署和测试 1.环境安装 HyperLedger Fabric 1.2.0环境的安装推荐一篇博客:http ...

最新文章

  1. 人工智能高薪的背后……
  2. 根据windows域名找ip
  3. Java 8 Stream Api 中的 skip 和 limit 操作
  4. linux里hba状态_在Linux/Unix平台查看HBA卡的WWN号 和状态
  5. boost::python::enum_相关的测试程序
  6. opcenum在计算机服务找不到,OPC DCOM 问题处理
  7. 2020-02-14 转载 开发应该知道的Linux系统分析-网络篇
  8. linux 软键盘输入密码,Linux系统中使用屏幕键盘的方法
  9. 自加载宏让你的Excel支持正则处理函数
  10. wps怎么删除空白页?你学会了吗?
  11. PowerVR SDK记录
  12. 前端裁图-如何使用ps软件将矩形图片裁剪成圆角矩形
  13. 【点阵显示汉字“王”】C++
  14. 京东商城暂停所有地铁自提点:或因租金成本高
  15. BAT调用服务器的PHP文件时所遇到的问题
  16. 3dMax建模笔记(一):介绍3dMax和创建第一个模型Hello world
  17. 买整体橱柜的五大误区
  18. 在百度地图上开启 测距的功能
  19. idea配置logback彩色日志
  20. 51Nod1459 迷宫游戏(带权最短路)

热门文章

  1. MAVEN下载安装与配置Win10最新最详细
  2. linux split到指定目录,split命令_Linux split命令:切割(拆分)文件
  3. easyX像素鸟PixelBird
  4. 北航学长的NLP赛事教程!
  5. 独立钻石跳棋问题的C++实现
  6. pyqt5 ,实现串口调试助手
  7. 苹果页面设计规范吐血整理
  8. 听声音做钥匙?!慢放开锁音轨,黑客就能破解常用门锁,从33万种密钥中锁定3种
  9. 读书笔记-人月神话2
  10. 厚涂简不简单?怎么入门厚涂