日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

python 氣象設備UDP傳輸數據解析——筆記

系統 1687 0

文章目錄

  • 一、背景
  • 二、總結內容
    • 2.1 UDP通信服務端創建方式
      • **DUP采用的是無連接的套接字**
    • 2.2 16進制數據解析
    • 2.3 文件創建與數據儲存分析

一、背景

最近在處理公司的一設備,內置的DTU通過UDP向服務器發送16進制的數據報文,由于第一次接觸此類數據解析方式,在這里做總結與反省,避免大家走彎路

二、總結內容

2.1 UDP通信服務端創建方式

步驟

  1. 創建UDP的socket通信方式。
  2. 綁定具體的端口。
  3. 設置端口復用等待(這一步可以省略)
  4. 獲取數據。
  5. 向客戶端發送數據。
  6. 解析儲存數據。
  7. 關閉UDP的socket鏈接。

下面分別講解并總結,通過MVP的方式完成以上所有步驟,不做過多延展:

1. 創建UDP的socket通信方式。

            
              
                import
              
               socket
Server 
              
                =
              
               socket
              
                .
              
              socket
              
                (
              
              socket
              
                .
              
              AF_INET
              
                ,
              
               socket
              
                .
              
              SOCK_DGRAM
              
                )
              
            
          

在任何類型的通信開始之前,網絡應用程序都必須創建套接字。
套接字最初是為同一主機上的應用程序所創建,使得主機上運行的一個程序(又名一個進程)與另一個運行的程序進行通信。這就是所謂的進程間通信(Inter Process Communication,IPC)
嵌套字有兩種類型:

  • 基于文件的:AF_UNIX
  • 面向網絡的:AF_INET(面向IPv4)、AF_INET6(面向IPv6)

DUP采用的是無連接的套接字

  • 特點:不可靠(局網內還是比較可靠的),開銷小。為了創建UDP套接字,必須使用SOCK_DGRAM作為套接字類型。UDP套接字的SOCK_DGRAM名字來自于單詞“datagram”(數據報)。

2. 綁定具體的端口

            
              Server
              
                .
              
              bind
              
                (
              
              
                ""
              
              
                ,
              
              
                8600
              
              
                )
              
            
          

bind 表示將創建好的Server綁定到具體的端口,注意:
當作為UDP的服務端時,前面的IP地址是可以省略的,后面是端口號有效的端口號范圍為0~65535(小于1024的端口號預留給了系統)

**3.設置端口復用等待(這一步可以省略) **

            
              Server
              
                .
              
              setsockopt
              
                (
              
              socket
              
                .
              
              IPPROTO_IP
              
                ,
              
               socket
              
                .
              
              SO_REUSEADDR
              
                ,
              
              
                1
              
              
                )
              
            
          

如果端口被使用過,并且利用Socket.close()關閉了端口鏈接,但是端口還沒有釋放,可以用上述函數來進行等待端口的重調用。

4. 獲取數據

            
              Msg
              
                ,
              
               ClientAddr 
              
                =
              
               Server
              
                .
              
              recvfrom
              
                (
              
              
                1024
              
              
                )
              
            
          

在UDP中使用recvform返回的是客戶端發送過來的**字節流(10進制、ASCII碼、16進制等)**與客戶端的IP地址,1024表示緩存數據的大小。

5. 向客戶端發送數據

            
              Server
              
                .
              
              sendto
              
                (
              
              Data
              
                )
              
            
          

一般UDP服務器在接收到數據后會向客戶端發送心跳包確認,可以通過此函數發送數據。

6. 解析數據

            
              Data 
              
                =
              
               binascii
              
                .
              
              b2a_hex
              
                (
              
              Msg
              
                )
              
            
          

此函數是將傳送過來的字節流報文數據解析成16進制數據。相關用法見字節流轉換成ASCII碼

7. 關閉UDP的socket鏈接

            
              Server
              
                .
              
              close
              
                (
              
              
                )
              
            
          

沒什么好講的,一定要有這個就行,不然下一次沒法繼續用這個端口。

2.2 16進制數據解析

1. 報文時間解析

            
              Time 
              
                =
              
               datetime
              
                .
              
              datetime
              
                .
              
              strptime
              
                (
              
              Data
              
                [
              
              
                26
              
              
                :
              
              
                38
              
              
                ]
              
              
                ,
              
              
                "%y%m%d%H%M%S"
              
              
                )
              
              
                # 解析時間
              
            
          

由于時間是十進制數據,這里不用做16進制轉換,直接通過datetime的strptime方法進行數據轉換。

2. 16進制轉換成10進制,再轉換成ASCII碼

            
              
                chr
              
              
                (
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                224
              
              
                +
              
              
                (
              
              i 
              
                -
              
              
                2
              
              
                )
              
              
                :
              
              
                224
              
              
                +
              
               i
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                )
              
            
          

int(num, 16) 將16進制轉換成10進制
chr(十進制)解析出對應的ASCII碼

2.3 文件創建與數據儲存分析

不得不說在儲存數據文件的時候遇到了很多的坑,現在總結:
坑1:如何自動創建 年->月->日的文件夾結構?

在自己創建文件夾的時候有想到過使用 makedirs() 函數鏈式創建文件夾,但是在判斷文件夾是否存在的時候一直報錯,一直以為是在makedirs()使用不當造成的,有想過聯合使用 chdir 函數與 mkdir() 函數來進行逐級的文件夾創建,最后效果也不是特別好。后來仔細查了好久的資料發現:

            
              
                if
              
              
                not
              
               os
              
                .
              
              path
              
                .
              
              exists
              
                (
              
              NewPath
              
                )
              
              
                :
              
              
    os
              
                .
              
              makedirs
              
                (
              
              NewPath
              
                )
              
            
          

在默認的IDLE中判斷文件夾是否存在時,一直是有問題會報錯的,折騰了好久,后來改為:

            
              
                if
              
              
                not
              
               os
              
                .
              
              path
              
                .
              
              isdir
              
                (
              
              FileDir
              
                )
              
              
                :
              
              
     os
              
                .
              
              makedirs
              
                (
              
              FileDir
              
                )
              
            
          

才沒有報錯,這里做筆記好好提醒一下自己。

以上是我總結的所有錯誤,希望看到這篇帖子的你能夠避開這些坑。下面附上我完整的UDP報文接收以及解析的代碼:

            
              
                #!/usr/local/bin/python3
              
              
                # coding:utf-8
              
              
                import
              
               socket

              
                import
              
               binascii

              
                import
              
               datetime

              
                import
              
               os

              
                import
              
               csv


              
                '''
作者:Zflyee
Mailto: zflyee@126.com
'''
              
              

Server 
              
                =
              
               socket
              
                .
              
              socket
              
                (
              
              socket
              
                .
              
              AF_INET
              
                ,
              
               socket
              
                .
              
              SOCK_DGRAM
              
                )
              
              
                # 創建UDP傳輸數據
              
              
                # Server.setsockopt(socket.IPPROTO_IP, socket.SO_REUSEADDR, 1)    # 快速實現端口復用
              
              

Server
              
                .
              
              bind
              
                (
              
              
                (
              
              
                ""
              
              
                ,
              
              
                8600
              
              
                )
              
              
                )
              
              
                print
              
              
                (
              
              u
              
                "已綁定本機端口:8600,正在監聽數據..."
              
              
                )
              
              
                def
              
              
                DataParsing
              
              
                (
              
              Data
              
                )
              
              
                :
              
              
    Time 
              
                =
              
               datetime
              
                .
              
              datetime
              
                .
              
              strptime
              
                (
              
              Data
              
                [
              
              
                26
              
              
                :
              
              
                38
              
              
                ]
              
              
                ,
              
              
                "%y%m%d%H%M%S"
              
              
                )
              
              
                # 解析時間
              
              

    Voltage 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                44
              
              
                :
              
              
                46
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 電壓數據
              
              

    Temp 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                60
              
              
                :
              
              
                64
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 實時溫度數據
              
              

    Temp_1h_max 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                70
              
              
                :
              
              
                74
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 溫度小時最大值
              
              

    Temp_1h_min 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                80
              
              
                :
              
              
                84
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 溫度小時最小值
              
              

    Hum 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                90
              
              
                :
              
              
                94
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 濕度數據
              
              

    Hum_1h_max 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                100
              
              
                :
              
              
                104
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 濕度小時最大值
              
              

    Hum_1h_min 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                110
              
              
                :
              
              
                114
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 濕度小時最小值
              
              

    Pa 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                120
              
              
                :
              
              
                124
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 氣壓數據
              
              

    Pa_1h_max 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                130
              
              
                :
              
              
                134
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 氣壓小時最大值
              
              

    Pa_1h_min 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                150
              
              
                :
              
              
                154
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 氣壓小時最小值
              
              

    WindSpd 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                140
              
              
                :
              
              
                144
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 瞬時風速值
              
              

    WindSpd_10min_avg 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                160
              
              
                :
              
              
                164
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 10分鐘風速平均值
              
              

    WindSpd_max 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                170
              
              
                :
              
              
                174
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 當前風速最大值
              
              

    WindSpd_min 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                180
              
              
                :
              
              
                184
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 當前風速最小值
              
              

    WindDir 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                190
              
              
                :
              
              
                194
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 當前風向瞬時值
              
              

    WindDir_10min_avg 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                200
              
              
                :
              
              
                204
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 10分鐘風向平均值
              
              

    Rain_1day 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                210
              
              
                :
              
              
                214
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                /
              
              
                10.0
              
              
                # 當日降雨量
              
              
                # 推算緯度數據長度
              
              
    Lati_len 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                220
              
              
                :
              
              
                224
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                # 轉換為10進制
              
              
    Lati 
              
                =
              
              
                ""
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                2
              
              
                ,
              
               Lati_len 
              
                *
              
              
                2
              
              
                ,
              
              
                2
              
              
                )
              
              
                :
              
              
        Lati 
              
                +=
              
              
                (
              
              
                chr
              
              
                (
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                224
              
              
                +
              
              
                (
              
              i 
              
                -
              
              
                2
              
              
                )
              
              
                :
              
              
                224
              
              
                +
              
               i
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                )
              
              
                )
              
              
                # 推算維度長度與數據
              
              
    Long_len 
              
                =
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                250
              
              
                :
              
              
                252
              
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
    Long 
              
                =
              
              
                ""
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                2
              
              
                ,
              
               Long_len 
              
                *
              
              
                2
              
              
                ,
              
              
                2
              
              
                )
              
              
                :
              
              
        Long 
              
                +=
              
              
                (
              
              
                chr
              
              
                (
              
              
                int
              
              
                (
              
              Data
              
                [
              
              
                254
              
              
                +
              
              
                (
              
              i 
              
                -
              
              
                2
              
              
                )
              
              
                :
              
              
                254
              
              
                +
              
               i
              
                ]
              
              
                ,
              
              
                16
              
              
                )
              
              
                )
              
              
                )
              
              
                # 組裝數據
              
              
    DataList 
              
                =
              
              
                [
              
              Time
              
                ,
              
               WindSpd
              
                ,
              
               WindSpd_10min_avg
              
                ,
              
               WindSpd_max
              
                ,
              
               WindSpd_min
              
                ,
              
               WindDir
              
                ,
              
               WindDir_10min_avg
              
                ,
              
              
                Temp
              
                ,
              
               Temp_1h_max
              
                ,
              
               Temp_1h_min
              
                ,
              
               Hum
              
                ,
              
               Hum_1h_max
              
                ,
              
               Hum_1h_min
              
                ,
              
               Pa
              
                ,
              
               Pa_1h_max
              
                ,
              
               Pa_1h_min
              
                ,
              
               Rain_1day
              
                ,
              
              
                Voltage
              
                ]
              
              
                # 創建文件路徑
              
              
    Path 
              
                =
              
              
                "E:\\富奧通\\data\\SY_FWS600\\"
              
              
    Text 
              
                =
              
               os
              
                .
              
              path
              
                .
              
              join
              
                (
              
              Path
              
                ,
              
               Time
              
                .
              
              strftime
              
                (
              
              
                "%Y"
              
              
                )
              
              
                ,
              
               Time
              
                .
              
              strftime
              
                (
              
              
                "%m"
              
              
                )
              
              
                )
              
              
                +
              
              
                "\\"
              
              
                +
              
               Time
              
                .
              
              strftime
              
                (
              
              
                "%d"
              
              
                )
              
              
                +
              
              
                ".csv"
              
              
    FileDir 
              
                =
              
               os
              
                .
              
              path
              
                .
              
              split
              
                (
              
              Text
              
                )
              
              
                [
              
              
                0
              
              
                ]
              
              
                if
              
              
                not
              
               os
              
                .
              
              path
              
                .
              
              isdir
              
                (
              
              FileDir
              
                )
              
              
                :
              
              
        os
              
                .
              
              makedirs
              
                (
              
              FileDir
              
                )
              
              
                # 寫入數據
              
              
                with
              
              
                open
              
              
                (
              
              Text
              
                ,
              
              
                "a+"
              
              
                ,
              
               newline
              
                =
              
              
                ""
              
              
                )
              
              
                as
              
               f
              
                :
              
              
        Writer 
              
                =
              
               csv
              
                .
              
              writer
              
                (
              
              f
              
                )
              
              
        Writer
              
                .
              
              writerow
              
                (
              
              DataList
              
                )
              
              
                # 儲存提示
              
              
                print
              
              
                (
              
              u
              
                "{}時刻數據已成功儲存。"
              
              
                .
              
              
                format
              
              
                (
              
              Time
              
                )
              
              
                )
              
              
                while
              
              
                True
              
              
                :
              
              
                try
              
              
                :
              
              
        Msg
              
                ,
              
               ClientAddr 
              
                =
              
               Server
              
                .
              
              recvfrom
              
                (
              
              
                1024
              
              
                )
              
              
        Data 
              
                =
              
               binascii
              
                .
              
              b2a_hex
              
                (
              
              Msg
              
                )
              
              
                # 將數據轉換成16進制數據
              
              
        Data 
              
                =
              
              
                str
              
              
                (
              
              Data
              
                ,
              
               encoding
              
                =
              
              
                "utf-8"
              
              
                )
              
              
                print
              
              
                (
              
              u
              
                "從{0}的{1}端口得到如下數據:\n{2}"
              
              
                .
              
              
                format
              
              
                (
              
              ClientAddr
              
                [
              
              
                0
              
              
                ]
              
              
                ,
              
               ClientAddr
              
                [
              
              
                1
              
              
                ]
              
              
                ,
              
               Data
              
                )
              
              
                )
              
              
                if
              
               Data
              
                [
              
              
                0
              
              
                :
              
              
                2
              
              
                ]
              
              
                ==
              
              
                "7b"
              
              
                :
              
              
            Content 
              
                =
              
              
                "7B810010"
              
              
                +
              
               Data
              
                [
              
              
                8
              
              
                :
              
              
                30
              
              
                ]
              
              
                +
              
              
                "7B"
              
              
            Response 
              
                =
              
               binascii
              
                .
              
              a2b_hex
              
                (
              
              Content
              
                )
              
              
            Server
              
                .
              
              sendto
              
                (
              
              Response
              
                ,
              
               ClientAddr
              
                )
              
              
                # 回復客戶端數據
              
              
                print
              
              
                (
              
              u
              
                "已回復客戶端"
              
              
                )
              
              
                elif
              
               Data
              
                [
              
              
                0
              
              
                :
              
              
                2
              
              
                ]
              
              
                ==
              
              
                '01'
              
              
                :
              
              
            DataParsing
              
                (
              
              Data
              
                )
              
              
                else
              
              
                :
              
              
                print
              
              
                (
              
              u
              
                "%%%%%%%%%%%%%%%數據報錯,重新獲取%%%%%%%%%%%%%%%"
              
              
                )
              
              
                continue
              
              
                except
              
              
                :
              
              
                print
              
              
                (
              
              u
              
                "%%%%%%%%%%%%%%%數據報錯,重新獲取%%%%%%%%%%%%%%%"
              
              
                )
              
              
                continue
              
              


Server
              
                .
              
              close
              
                (
              
              
                )
              
            
          

更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 嘉鱼县| 会泽县| 宜宾县| 东兰县| 和龙市| 定南县| 衡山县| 乳山市| 长汀县| 盈江县| 腾冲县| 仙游县| 巴南区| 德兴市| 邯郸县| 新安县| 五寨县| 封丘县| 荔浦县| 泾源县| 辽阳县| 瑞丽市| 玉山县| 江北区| 黑河市| 鄱阳县| 宜城市| 高阳县| 东乡| 海门市| 甘泉县| 克拉玛依市| 嘉黎县| 那坡县| 宁阳县| 桓仁| 马尔康县| 高要市| 邳州市| 赤城县| 洪湖市|