Golang在物联网(IoT)中的应用探索

Golang在物联网(IoT)中的应用探索 各位,Go语言可以用于物联网设备编程吗? 主要编程需求是:

能够连接多个设备 能够存储数据 应支持 [Arduino] 或 [Raspberry Pi] 运行速度应相当快

Go语言在物联网编程中可靠吗?

7 回复

好的,谢谢您,先生。

更多关于Golang在物联网(IoT)中的应用探索的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


根据我有限的经验,树莓派并不可靠。可以看看UP Board。价格稍高,但它们是经过Linux内核优化的稳定产品。

还有专为这类用例设计的 TinyGo:https://tinygo.org/

你可以在多种不同的微控制器开发板上编译并运行 TinyGo 程序,例如 BBC micro:bitArduino Uno

只要在支持的平台(微处理器)上运行Go程序,就没有问题。

对于Arduino来说,这不可行,因为Go是专门为计算而设计的。最好还是坚持使用C/C++。如果你想在嵌入式级别获得Go支持,可以考虑为开发团队做出贡献。

对于树莓派,你需要记住像这样交叉编译你的程序:

$ env GOOS=linux GOARCH=arm GOARM=5 go build <path/to/program>

Go在边缘数据处理和后端服务器方面是可靠的。对于传感器/执行器接口,根据你的设计,微控制器汇编 / C / C++ 会更合适。

Sujith-sunny:

编程的主要需求是:

能够连接多种设备 能够存储数据 应支持 [Arduino] 或 [Raspberry Pi] 速度应相当快 Go 语言对于物联网编程可靠吗?

绝对可靠。我用 Go 语言编写了一个 SCADA IIoT 系统(实时监控和命令),得益于 goroutines,能够实时连接到许多设备。我还在 Raspberry Pi 上工作过(参见此处了解方法)。是的,它非常快速和可靠。

hollowaykeanho:

你可以考虑为团队进行开发。

bklimczak:

还有 TinyGo。

抱歉有一些打字错误。感谢你的支持 @bklimczak。 🙂

我原本想表达的是“你可以帮助开发团队在嵌入式微控制器上启用 Go”。根据我对 TinyGo 的测试,你必须遵守一些规则:

  1. 避免堆内存分配(堆分配 | TinyGo
  2. 目前不支持 map 类型(Go 语言特性 | TinyGo

考虑到从互联网导入 Go 包的便利性,你在导入 Go 包时必须非常、非常小心,因为很多包内部都使用了 map 数据类型。大多数时候,编程体验就像踮着脚尖走路。在我看来,这相当费力,这就是为什么我(目前)不推荐在微控制器上使用 Go。

如果你能解决这些难题并为开发团队(例如 TinyGo / Go 开发团队)做出贡献,我相信整个 Go 社区都会感谢你的努力。 🙂

如果你需要小型板卡,但由于某些原因必须严格使用 Go,你可以考虑那些非常小的单板计算机,这样你就不需要处处受限了:

  1. 购买 Compute Module 3+ – Raspberry Pi
  2. https://www.friendlyarm.com/index.php?route=product/product&product_id=132

探索愉快。

Go语言非常适合物联网(IoT)开发,特别是对于需要并发连接、高效数据处理和跨平台部署的场景。以下是具体实现示例:

1. 多设备连接(使用goroutine和channel)

package main

import (
    "fmt"
    "net"
    "sync"
    "time"
)

type DeviceManager struct {
    devices map[string]net.Conn
    mu      sync.RWMutex
    dataCh  chan DeviceData
}

type DeviceData struct {
    ID   string
    Data []byte
}

func (dm *DeviceManager) HandleDevice(conn net.Conn, deviceID string) {
    defer conn.Close()
    buffer := make([]byte, 1024)
    
    for {
        n, err := conn.Read(buffer)
        if err != nil {
            fmt.Printf("Device %s disconnected\n", deviceID)
            dm.mu.Lock()
            delete(dm.devices, deviceID)
            dm.mu.Unlock()
            return
        }
        
        dm.dataCh <- DeviceData{
            ID:   deviceID,
            Data: buffer[:n],
        }
    }
}

func (dm *DeviceManager) StartServer(port string) {
    ln, _ := net.Listen("tcp", ":"+port)
    defer ln.Close()
    
    for {
        conn, _ := ln.Accept()
        deviceID := fmt.Sprintf("device_%d", time.Now().UnixNano())
        
        dm.mu.Lock()
        dm.devices[deviceID] = conn
        dm.mu.Unlock()
        
        go dm.HandleDevice(conn, deviceID)
    }
}

2. 数据存储(使用SQLite)

package main

import (
    "database/sql"
    "log"
    "time"
    _ "github.com/mattn/go-sqlite3"
)

type DataStore struct {
    db *sql.DB
}

func NewDataStore(dbPath string) (*DataStore, error) {
    db, err := sql.Open("sqlite3", dbPath)
    if err != nil {
        return nil, err
    }
    
    // 创建设备数据表
    createTable := `
    CREATE TABLE IF NOT EXISTS device_data (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        device_id TEXT NOT NULL,
        data BLOB,
        timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
    )`
    
    _, err = db.Exec(createTable)
    if err != nil {
        return nil, err
    }
    
    return &DataStore{db: db}, nil
}

func (ds *DataStore) SaveData(deviceID string, data []byte) error {
    _, err := ds.db.Exec(
        "INSERT INTO device_data (device_id, data) VALUES (?, ?)",
        deviceID, data,
    )
    return err
}

func (ds *DataStore) GetRecentData(deviceID string, limit int) ([]DeviceData, error) {
    rows, err := ds.db.Query(
        "SELECT data, timestamp FROM device_data WHERE device_id = ? ORDER BY timestamp DESC LIMIT ?",
        deviceID, limit,
    )
    if err != nil {
        return nil, err
    }
    defer rows.Close()
    
    var results []DeviceData
    for rows.Next() {
        var data []byte
        var timestamp time.Time
        if err := rows.Scan(&data, &timestamp); err != nil {
            return nil, err
        }
        results = append(results, DeviceData{
            ID:   deviceID,
            Data: data,
        })
    }
    return results, nil
}

3. Raspberry Pi GPIO控制

package main

import (
    "fmt"
    "time"
    "github.com/stianeikeland/go-rpio/v4"
)

func ControlGPIO() {
    // 初始化GPIO
    err := rpio.Open()
    if err != nil {
        fmt.Println("Failed to open GPIO:", err)
        return
    }
    defer rpio.Close()
    
    // 设置引脚17为输出模式
    pin := rpio.Pin(17)
    pin.Output()
    
    // 控制LED闪烁
    for i := 0; i < 10; i++ {
        pin.High() // 打开
        time.Sleep(500 * time.Millisecond)
        pin.Low() // 关闭
        time.Sleep(500 * time.Millisecond)
    }
}

4. 完整的IoT设备示例

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "time"
)

type SensorData struct {
    DeviceID  string    `json:"device_id"`
    Temperature float64 `json:"temperature"`
    Humidity    float64 `json:"humidity"`
    Timestamp   int64   `json:"timestamp"`
}

type IoTDevice struct {
    ID       string
    dataCh   chan SensorData
    quitCh   chan bool
}

func (d *IoTDevice) StartSensing() {
    ticker := time.NewTicker(5 * time.Second)
    defer ticker.Stop()
    
    for {
        select {
        case <-ticker.C:
            // 模拟传感器数据
            data := SensorData{
                DeviceID:    d.ID,
                Temperature: 20 + (5 * (time.Now().Unix() % 10)),
                Humidity:    40 + (10 * (time.Now().Unix() % 10)),
                Timestamp:   time.Now().Unix(),
            }
            d.dataCh <- data
            
        case <-d.quitCh:
            return
        }
    }
}

func main() {
    // 创建设备管理器
    deviceManager := &DeviceManager{
        devices: make(map[string]net.Conn),
        dataCh:  make(chan DeviceData, 100),
    }
    
    // 创建数据存储
    dataStore, err := NewDataStore("./iot_data.db")
    if err != nil {
        log.Fatal(err)
    }
    
    // 启动HTTP API
    http.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
        var data SensorData
        json.NewDecoder(r.Body).Decode(&data)
        
        jsonData, _ := json.Marshal(data)
        dataStore.SaveData(data.DeviceID, jsonData)
        
        w.WriteHeader(http.StatusOK)
        json.NewEncoder(w).Encode(map[string]string{"status": "success"})
    })
    
    // 启动TCP服务器处理设备连接
    go deviceManager.StartServer("8080")
    
    // 启动数据处理器
    go func() {
        for deviceData := range deviceManager.dataCh {
            // 处理设备数据
            fmt.Printf("Received from %s: %s\n", 
                deviceData.ID, 
                string(deviceData.Data))
            
            // 存储到数据库
            dataStore.SaveData(deviceData.ID, deviceData.Data)
        }
    }()
    
    // 启动HTTP服务器
    log.Fatal(http.ListenAndServe(":8081", nil))
}

性能特点:

  1. 并发处理:goroutine轻量级,可同时处理数千设备连接
  2. 内存效率:垃圾回收器优化,适合资源受限的嵌入式设备
  3. 编译部署:单二进制文件部署,依赖少
  4. 跨平台:支持ARM架构(Raspberry Pi),交叉编译简单
  5. 标准库丰富:内置HTTP、TCP、JSON等协议支持

对于Arduino,Go可通过串口通信或使用TinyGo编译器直接编程。Raspberry Pi上Go可直接运行,通过go-rpio等库控制GPIO。Go的静态编译特性确保在IoT设备上的快速启动和稳定运行。

回到顶部