模組----modbus_tk中TCP協議簡單應用
被告知說會考有關modbus_tk這個模組的東東,我和小夥伴們都驚呆了,很是捉雞啊~~~
關於這個模組,基本上就是零基礎,一步步來。以下都是我的個人見解,若有錯誤請大膽地指出來吧~~
=====================================================================================================================
第一步 做好基本準備工作
=====================================================================================================================
1.查閱modbus本身相關的資料,弄清楚它大概是什麼東東
2.安裝modbus_tool,裡面有個POLL和SLAVE,盡情去除錯吧,有利於弄清楚modbus的結構,還可以測試程式哦~~
樓主當時是沒有弄modbus_tool,直接程序序瞎倒騰,後來被高手指點才跑去用modbus_tool,果然豁然開朗
=====================================================================================================================
第二步 安裝modbus_tk
=====================================================================================================================
在linux和windows上安裝會有點不一樣,其實就是windows在前面多了一個步驟。
----------------------------------------------------------------------------------------------------------------
linux:
在官網下載完modbus_tk,解壓進去就會發現有個setup.py的檔案,直接在此目錄下開啟終端,執行python setup.py
就會有個提示help告訴你怎麼安裝,然後用install的那個引數就行了。
windows:
先下載安裝一個Modbus Tools.7z的東東,之後就和在linux的操作一樣一樣的了。
這個東西是安裝python其它模組的一個輔助軟體,就是說有了這個東西,它才能去裝其它的一些模組
linux 本來就有帶Modbus Tools,所以可以直接安裝
注:這個Modbus Tools.7z是python裡面的一個模組,不是前面說的modbus_tool哦~
=====================================================================================================================第三步 看示例吧·~
=====================================================================================================================
示例一 前輩的示例 (被我改了一些,原始版的木有了,懶得去再打一次,將就用修改版的吧)
------------------------------------------------------------------------------------------------------------
得把slave先執行,才能用master讀取或者修改。
#!/usr/bin/python
# -*- coding: utf-8 -*-
# filename: slave.py
# ------------------------------------------------------------------------------
# 匯入外部模組
# ------------------------------------------------------------------------------
import struct
import modbus_tk.defines
import modbus_tk.modbus
import modbus_tk.modbus_tcp
import time
import random
# ------------------------------------------------------------------------------
# 主程式
# ------------------------------------------------------------------------------
try:
server = modbus_tk.modbus_tcp.TcpServer()
#注意,若是在linux裡面執行,埠就不能不寫了,否則就要用root才能跑,其它使用者只能用1024以上的埠
#這裡的埠和地址都是預設的,地址是本地:
#原來的程式:server = modbus_tk.modbus_tcp.TcpServer(port=502, address='0.0.0.0', timeout_in_sec=3)
server.start()
slave_1 = server.add_slave(1)
slave_1.add_block('block1', modbus_tk.defines.ANALOG_INPUTS, 0, 2)
#給slave_1新增一個模組(模組名,只讀,地址,長度)
while 1:
bb = random.random()
aa = struct.unpack('>HH', struct.pack('>f', bb))
print 'bb:', bb
print "aa:", aa
slave_1.set_values('block1', 0, aa)
print '========='
time.sleep(3)
except:
print '============error==========='
finally:
print '=========stop========'
server.stop()
#!/usr/bin/python
# -*- coding: utf-8 -*-
# filename: master.py
# ------------------------------------------------------------------------------
# 匯入外部模組
# ------------------------------------------------------------------------------
import modbus_tk
import modbus_tk.defines
import modbus_tk.modbus
import modbus_tk.modbus_tcp
import struct
import time
# ------------------------------------------------------------------------------
# 主程式
# ------------------------------------------------------------------------------
try:
while 1:
master = modbus_tk.modbus_tcp.TcpMaster()
#('0.0.0.0', 502) (master ip 地址,埠)
#注意用linux的童鞋們,埠小於1024得用root才能跑起來哦~
#為這個問題樓主曾經也折騰了一陣,後來才發現居然是這個原因·····
#這裡有個問題就是原來我是用'0.0.0.0'這個地址的。
#但是它應該不能算一個ip地址了,這個是代表現有的ip地址均可的意思,有種萬用字元的感覺
#在slave中可以用它,但是在master中不行,一定要給它指明一個具體的地址,看來它也有選擇困難症
master.set_timeout(3) #timeout表示若超過3秒沒有連線上slave就會自動斷開
#set_timeout(3)不知是何意----重新把timeout時間設定成3秒,在生成master那裡就可以進行初始化定義的,若沒有自定義就會用預設值
aa = master.execute(1, modbus_tk.defines.ANALOG_INPUTS, 0, 2)
#(slave id,只讀,block地址,長度:即位元組乘個數)
print 'aa:', aa, 'size', len(aa)
bb = struct.unpack('>f', struct.pack('>HH', aa[0], aa[1]))
#在slave中,是先打包成'>f'在以'>HH'解包的,在master中剛好相反
#struct.unpack裡解出來的是一個元組,可以用bb, = 或者輸出bb[0]
print 'bb:', bb[0]
time.sleep(3)
except Exception as e:
print '=========error========='
print e
finally:
print '=======stop======='
檢視埠是否已經開放 (用root許可權)
/etc/init.d/iptables status
/sbin/iptables -I INPUT -p tcp --dport 5023 -j ACCEPT # 開啟5023埠
/etc/rc.d/init.d/iptables save #儲存配置
/etc/rc.d/init.d/iptables restart #重啟服務
示例二 官網的示例 很坑爹····好多錯誤····不知道怎麼會放在官網上的·····果斷也被我改了
---------------------------------------------------------------------------------------------------------------------
#!/usr/bin/python
# -*- coding: utf-8 -*-
# filename: server_example.py
# ------------------------------------------------------------------------------
# 匯入外部模組
# ------------------------------------------------------------------------------
import modbus_tk
import modbus_tk.modbus_tcp as modbus_tcp
import modbus_tk.defines as mdef
import threading
import sys
# ------------------------------------------------------------------------------
# 主程式
# ------------------------------------------------------------------------------
logger = modbus_tk.utils.create_logger(name='console', record_format='%(message)s')
if __name__ == '__main__':
try:
logger.info("running...")
logger.info("enter 'quit' for closing the server")
server = modbus_tcp.TcpServer(port=1152)
server.start()
#sever.start()可以在加了slave和模組以後,也可以不加直接裸奔~
#creates a slave with id 0
slave1 = server.add_slave(1)
#add 2 blocks of holding registers
slave1.add_block('a', mdef.HOLDING_REGISTERS, 0, 100) #address 0, length 100
slave1.add_block('b', mdef.HOLDING_REGISTERS, 200, 20) #address 200, length 20
#create another slave with id 5
slave5 = server.add_slave(5)
slave5.add_block('c', mdef.COILS, 0, 100)
slave5.add_block('d', mdef.HOLDING_REGISTERS, 0, 100)
#set the values of registers at address 0
slave1.set_values('a', 0, range(100))
while True:
cmd = sys.stdin.readline()
if cmd.find('quit')==0:
#當輸入的只有quit,程式就會退出
sys.stdout.write('bye-bye\r\n')
sys.exit(0)
finally:
server.stop()
#!/usr/bin/python
# -*- coding: utf-8 -*-
# filename: master_example.py
# ------------------------------------------------------------------------------
# 匯入外部模組
# ------------------------------------------------------------------------------
import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus_tcp as modbus_tcp
# ------------------------------------------------------------------------------
# 主程式
# ------------------------------------------------------------------------------
if __name__ == '__main__':
try:
#Connect to the slave
master = modbus_tcp.TcpMaster(port=1152)
print master.execute(1, cst.READ_HOLDING_REGISTERS, 10, 3)
master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 200, output_value=xrange(12))
print master.execute(1, cst.READ_HOLDING_REGISTERS, 10, 3)
except modbus_tk.modbus.ModbusError, e:
print "Modbus error", e.get_exception_code()
except Exception, e2:
print "Error", str(e2)
示例三 modbus_tk檔案中本身自帶的example
---------------------------------------------------------------------------------------------------------------------
slave
#!/usr/bin/env python
# -*- coding: utf_8 -*-
"""
Modbus TestKit: Implementation of Modbus protocol in python
(C)2009 - Luc Jean - [email protected]
(C)2009 - Apidev - http://www.apidev.fr
This is distributed under GNU LGPL license, see license.txt
"""
import sys
#add logging capability
import logging
import threading
import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus as modbus
import modbus_tk.modbus_tcp as modbus_tcp
logger = modbus_tk.utils.create_logger(name="console", record_format="%(message)s")
if __name__ == "__main__":
try:
#Create the server
server = modbus_tcp.TcpServer(port=1500)
logger.info("running...")
logger.info("enter 'quit' for closing the server")
server.start()
slave_1 = server.add_slave(1)
slave_1.add_block('0', cst.COILS, 0, 100)
slave_1.set_values('0', 0, range(100))
#range(100)為0-99的列表
while True:
cmd = sys.stdin.readline()
#這裡是進入程式以後,讀取每次輸入的命令:以回車來判斷命令是否輸入完畢
args = cmd.split(' ')
if cmd.find('quit')==0:
#當輸入的只有quit,程式就會退出
sys.stdout.write('bye-bye\r\n')
break
elif args[0]=='add_slave':
slave_id = int(args[1])
#slave id只能為int?是的
server.add_slave(slave_id)
sys.stdout.write('done: slave %d added\r\n' % (slave_id))
#write到哪裡去了?螢幕輸出去了~~
elif args[0]=='add_block':
slave_id = int(args[1])
name = args[2]
block_type = int(args[3])
starting_address = int(args[4])
length = int(args[5])
slave = server.get_slave(slave_id)
slave.add_block(name, block_type, starting_address, length)
sys.stdout.write('done: block %s added\r\n' % (name))
elif args[0]=='set_values':
slave_id = int(args[1])
name = args[2]
#這個name是slave_id對應的block的名字
address = int(args[3])
values = []
#這裡的values只可少設不可多設,否則就報錯退出程式
for v in args[4:]:
#value只能是int,就算是其他數字型別也報錯
#囧 好奇怪,明明平時int(0.1)也是可以的
values.append(int(v))
slave = server.get_slave(slave_id)
slave.set_values(name, address, values)
values = slave.get_values(name, address, len(values))
sys.stdout.write('done: values written: %s\r\n' % (str(values)))
elif args[0]=='get_values':
slave_id = int(args[1])
name = args[2]
address = int(args[3])
length = int(args[4])
slave = server.get_slave(slave_id)
values = slave.get_values(name, address, length)
sys.stdout.write('done: values read: %s\r\n' % (str(values)))
else:
sys.stdout.write("unknown command %s\r\n" % (args[0]))
finally:
server.stop()
master
#!/usr/bin/env python
# -*- coding: utf_8 -*-
"""
Modbus TestKit: Implementation of Modbus protocol in python
(C)2009 - Luc Jean - [email protected]
(C)2009 - Apidev - http://www.apidev.fr
This is distributed under GNU LGPL license, see license.txt
"""
import sys
#add logging capability
import logging
import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus_tcp as modbus_tcp
logger = modbus_tk.utils.create_logger("console")
if __name__ == "__main__":
try:
#Connect to the slave
master = modbus_tcp.TcpMaster(port=1500)
master.set_timeout(5.0)
logger.info("connected")
#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 100, 100))
#(slave id,Modbus資料模型,block地址,長度:即位元組乘個數)
#同一個slave下,不同block的Modbus資料模型可以是不一樣的
##################################################################################################
#下面的例子都需要自己在slave裡面新增slave(需要改下面的id)或block才能實現
#-------------------------------------------------------------------------------------------------
print cst.COILS #1-----1位讀寫
print cst.READ_COILS #1-----1位只讀
print cst.WRITE_SINGLE_COIL #5-----1位只寫
print cst.WRITE_MULTIPLE_COILS #15----1位寫
logger.info(master.execute(1, cst.READ_COILS, 0, 10))
#一位:所以個數是10,位元組是1 若給非0值,均會以1存入 預設值是(0,0,0,0,0,0,0,0,0,0)
#只寫的,這裡會輸出modbus的可識別的格式'>HH',即有兩個元素的元組:
a = logger.info(master.execute(1, cst.WRITE_SINGLE_COIL, 7, output_value=0))
#將slave的地址7的value改成1。
logger.info(master.execute(1, cst.READ_COILS, 0, 10))
#logger.info(master.execute(1, cst.WRITE_MULTIPLE_COILS, 5, output_value=xrange(12)))
print 'a =', a # a=None
#-------------------------------------------------------------------------------------------------
print cst.DISCRETE_INPUTS #2-----1位只讀
print cst.READ_DISCRETE_INPUTS #2-----1位只讀
#logger.info(master.execute(1, cst.READ_DISCRETE_INPUTS, 0, 8))
#一位:所以個數是8,位元組是1 若給非0值,均會以1存入 預設值是(0,0,0,0,0,0,0,0)
#-------------------------------------------------------------------------------------------------
print cst.HOLDING_REGISTERS #3-----16位讀寫
print cst.READ_HOLDING_REGISTERS #3-----16位只讀
print cst.WRITE_SINGLE_REGISTER #6-----16位寫
print cst.WRITE_MULTIPLE_REGISTERS #16----16位寫
#這裡讀取的是之前的資訊
#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 3))
#16位:所以個數是3,位元組是16 若給負值,會出錯 預設值是(0,0,0)
#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 100))
#logger.info(master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 0, output_value=[50, 1, 1, 1, 1, 1, 1, 1]))
#從地址0開始,後面8為全是1
#logger.info(master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 5, output_value=xrange(12)))
#從地址5開始,後面12位是xrange(12)
#這裡讀取的是改變後的資訊
#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 3))
#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 100))
#logger.info(master.execute(1, cst.WRITE_SINGLE_REGISTER, 5, output_value=1))
#-------------------------------------------------------------------------------------------------
print cst.ANALOG_INPUTS #4-----16位只讀
print cst.READ_INPUT_REGISTERS #4-----16位只讀
#logger.info(master.execute(1, cst.READ_INPUT_REGISTERS, 10, 12))
#16位:所以個數是3,位元組是16 若給負值,會出錯 預設值是(0,0,0,0,0,0,0,0,0,0,0,0)
##################################################################################################
except modbus_tk.modbus.ModbusError, e:
logger.error("%s- Code=%d" % (e, e.get_exception_code()))
更多資料 後來才發現原來modbus_tk檔案中自帶的doc資料夾下面有原始碼的 囧 看那個應該會很不錯
=====================================================================================================================
第四步 小總結
=====================================================================================================================
1.在linux上執行除了要注意埠,還要注意的就是防火牆的問題,我是直接把防火牆給關了的。
2.modbus本身可以傳輸16位無符號整數,如果要傳輸浮點數或者是32位無符號整數就要進行打包,具體看struct模組。
3.server和master的功能碼對應表
===================================================================
對於server(slave):
modbus_tk.defines.COILS: 1位讀寫 1
modbus_tk.defines.DISCRETE_INPUTS: 1位只讀 2
modbus_tk.defines.HOLDING_REGISTERS: 16位讀寫 3
modbus_tk.defines.ANALOG_INPUTS: 16位只讀 4
===================================================================
對於master(要於server對應起來):
modbus_tk.defines.COILS: 1-----1位讀寫
modbus_tk.defines.READ_COILS 1-----1位只讀
modbus_tk.defines.WRITE_SINGLE_COIL 5-----1位只寫,一個個寫的,更穩定,但效率低
modbus_tk.defines.WRITE_MULTIPLE_COILS 15----1位只寫,多個一起寫,穩定性一般,效率高
-------------------------------------------------------------------
modbus_tk.defines.DISCRETE_INPUTS: 2-----1位只讀
modbus_tk.defines.READ_DISCRETE_INPUTS 2-----1位只讀
-------------------------------------------------------------------
modbus_tk.defines.HOLDING_REGISTERS: 3-----16位讀寫
modbus_tk.defines.READ_HOLDING_REGISTERS 3-----16位只讀
modbus_tk.defines.WRITE_SINGLE_REGISTER 6-----16位寫,一個個寫的,更穩定,但效率低
modbus_tk.defines.WRITE_MULTIPLE_REGISTERS 16----16位寫,多個一起寫,穩定性一般,效率高
-------------------------------------------------------------------
modbus_tk.defines.ANALOG_INPUTS: 4-----16位只讀
modbus_tk.defines.READ_INPUT_REGISTERS 4-----16位只讀
===================================================================
相關推薦
模組----modbus_tk中TCP協議簡單應用
被告知說會考有關modbus_tk這個模組的東東,我和小夥伴們都驚呆了,很是捉雞啊~~~ 關於這個模組,基本上就是零基礎,一步步來。以下都是我的個人見解,若有錯誤請大膽地指出來吧~~ =======================================
Http協議與TCP協議簡單理解( 轉 )
art 這也 這一 傳輸協議 方便 編寫 庫服務器 為我 之間 在C#編寫代碼,很多時候會遇到Http協議或者TCP協議,這裏做一個簡單的理解。TCP協議對應於傳輸層,而HTTP協議對應於應用層,從本質上來說,二者沒有可比性。Http協議是建立在TCP協議基礎之上的,當瀏覽
【網絡協議】TCP協議簡單介紹
tis sim 發生 ron html tcp協議 緩沖 應用程序 不可 ? ? 本文僅僅是對TCP協議做個簡要的介紹。? ? TCP協議,即傳輸控制協議。與UDP協
基於TCP協議簡單qq聊天
pre inf 基於 port byte while enc == con #server端 import socket ip_port = (‘127.0.0.1‘,8080) sk = socket.socket() sk.setsockopt(socket.SOL
python中property的簡單應用場景
python color per 註意 print ddc cfa img shadow 多註意看最後的兩個print,一個是name,一個是name2當然可以再增加個name3python中property的簡單應用場景
Unity中MVC的簡單應用
model using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 模型委託(當用戶資訊發生變化時執行) /// </summ
java中MongoDB的簡單應用例項
1 首先載入 MongoDB的jar包。下載Jar包連結 2然後進行相應的配置。如我當前專案是在web-pom.xml 的的節點下配置。 <dependency> <groupId>org.mo
TCP協議簡單講解
TCP協議 TCP(Transmission Control Protocol 傳輸控制協議)是一種面向連線的、可靠的、基於位元組流的傳輸層通訊協議。 TCP包頭格式 首先,源埠號和目標埠號是不可少的,埠號的存在,資料就知道應該發給哪個應用。
maven(五)在eclipse中maven的簡單應用
1、匯入maven專案 在4中寫了maven的專案,現在把他匯入進來。選擇選單項 File,然後選擇 Import,我們會看到一個 Import 對話方塊,在該對話方塊中選擇 Maven目錄下的 Maven Projects,然後點選Next, 就會出現 Im
Http協議與TCP協議簡單理解後續
大約2年前寫了一篇關於HTTP協議與TCP協議的文章,原文連結。最近再次簡單讀了一遍《TCP/IP協議卷》,有了一些新的理解。這篇文章沒有一個很好的連貫性,都是我在讀書過程中總結的知識點,整體比較鬆散,但是個人感覺知識點都是非常重要,有很多地方讓我明白了迷惑很久的問題。
QT:HTTP協議簡單應用
HTTP協議 QNetworkAccessManager QNetworkReply 《案例》QT實現HTTP文字瀏覽器 /* HTTP文字瀏覽器 - 程式碼演示 */// HttpDialog.h #ifndef HTTPDIALOGH #define HTTPDIAL
python lxml中etree的簡單應用1
我一般都是通過xpath解析DOM樹的時候會使用lxml的etree,可以很方便的從html原始碼中得到自己想要的內容。 這裡主要介紹一下我常用到的兩個方法,分別是etree.HTML()和etree.tostrint()。 1.etree.HTML() etree.H
python lxml中etree的簡單應用3
本次主要介紹,無論使用的xpath表示式中是否包含text()方法,最後都可以獲取目標標籤下的文字。使用的依然是etree.HTML和etree.tostring方法。1.思路首先將字串原始碼轉換成_Element物件,然後使用_Element物件的xpath()方法解析xp
計算機網路中TCP協議與UDP協議的比較
在計算機網路層次結構的運輸層中,TCP協議、UDP協議解決了端到端的通訊問題。 在這裡的協議即為軟體,用以解決計算機網路的通訊互聯問題。 計算機網路層次結構概述 現代計算機網路基本層次結構由5個層次組成,自頂向下為:應用層、運輸層、網路層、資料
Asp.net core中RedisMQ的簡單應用
最近一個外部的專案,使用到了訊息佇列,本來是用rabbitmq實現的,但是由於是部署到別人家的伺服器上,想盡量簡化一些,專案中本來也要接入了redis快取,就嘗試使用redis來實現簡單的訊息佇列。 使用redis做訊息佇列有兩種方法,一種是使用pub/sub,另一種是使用list結構,配合brpop來
利用node.js中的net模組使用tcp協議
一、單向通訊 server.js 使用net模組建立一個tcp server監聽tcp連線事件 var net=require('net') var server=net.createServ
TCP-IP之應用層協議
傳輸協議 images gateway 1-1 大學 表示 進制 技術 dom 應用層協議是多種多樣的,比如 DNS、FTP、Telnet、SMTP、HTTP、RIP、NFS 一、DNS DNS (Domain Name Service 域名服務) 協議基於 UDP,使用
python3實現TCP協議的簡單服務器和客戶端
由於 轉載 while encoding ont ans 令行 cti 數據 利用python3來實現TCP協議,和UDP類似。UDP應用於及時通信,而TCP協議用來傳送文件、命令等操作,因為這些數據不允許丟失,否則會造成文件錯誤或命令混亂。下面代碼就是模擬客戶端通過命令行
網絡編程----------SOCKET編程實現簡單的TCP協議
water 實現 保活定時器 log 超時重傳 color 斷開連接 超時 面向連接 首先我們須要大致了解TCP的幾點知識: 1.TCP的特點:面向連接的可靠性傳輸 2.TCP的三次握手建立連接和四次揮手釋放連接。但為什麽TCP要三次握手建立連接呢? 答:由於
TCP協議中的三次握手和四次揮手(圖解)(轉)
繼續 丟失 get 所有 如果 idt 請求報文 網絡 center 轉自:http://blog.csdn.net/whuslei/article/details/6667471 建立TCP需要三次握手才能建立,而斷開連接則需要四次握手。整個過程如下圖所示: 先來看看如