Принципы работы и советы по интеграции

API Fontera PTL работает на базе HTTP. Основной форма передачи сообщений: JSON.

Автоматическая документация (генерация через Swagger) доступна по адресу /docs вашего стенда. Там же отправить тестовый запрос и увидеть ответ.

Концептуальная схема отправки команд до PTL модулей

Отправка на схеме выполняется через /turn_on, а чтение через /ptls.

схема отправки команд

Примеры реализации

Все представленные примеры приведены исключительно в ознакомительных целях. Они не предназначены для использования в продуктивной среде без соответствующей доработки и тестирования.

Отправка зажигания, ожидание и чтение состояния модулей

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

type Command struct {
    Role   string `json:"role,omitempty"`
    Unit   int    `json:"unit,omitempty"`
    Number int    `json:"number,omitempty"`
    Sub    int    `json:"sub,omitempty"`
    Color  string `json:"color,omitempty"`
}

type ControllerCommands struct {
    ControllerIP string    `json:"controller_ip"`
    Commands     []Command `json:"commands"`
}

type PTLQuery struct {
    IP          string `json:"ip"`
    ClearAfter  bool   `json:"clear_after"`
    Mode        string `json:"mode,omitempty"`
    Role        string `json:"role,omitempty"`
}

func main() {
    baseURL := "http://localhost:8000" // Заменить на реальный адрес API
    controllerIP := "192.168.0.100"

    turnOnPayload := ControllerCommands{
        ControllerIP: controllerIP,
        Commands: []Command{
            {
                Role:   "picker",
                Unit:   1,
                Number: 9999,
                Color:  "Red",
            },
        },
    }

    sendJSON(baseURL+"/turn_on", turnOnPayload)

    time.Sleep(2 * time.Second)

    ptlQuery := PTLQuery{
        IP:         controllerIP,
        ClearAfter: false,
        Role:       "picker",
    }

    sendJSON(baseURL+"/ptls", ptlQuery)
}

func sendJSON(url string, data interface{}) {
    payloadBytes, err := json.Marshal(data)
    if err != nil {
        panic(err)
    }

    req, err := http.NewRequest("POST", url, bytes.NewBuffer(payloadBytes))
    if err != nil {
        panic(err)
    }
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Printf("Response from %s:\n%s\n", url, string(body))
}

Проверка состояния конкретного модуля

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

type PTLQuery struct {
    IP         string `json:"ip"`
    ClearAfter bool   `json:"clear_after"`
}

type PTLResponse struct {
    Unit       int    `json:"unit"`
    Controller string `json:"controller"`
    State      string `json:"state,omitempty"`
    Color      string `json:"color,omitempty"`
    Number     int    `json:"number,omitempty"`
    Sub        int    `json:"sub,omitempty"`
}

func main() {
    baseURL := "http://localhost:8000" // Заменить на актуальный
    controllerIP := "192.168.0.100"    // Заменить на IP контроллера
    targetUnit := 55

    query := PTLQuery{
        IP:         controllerIP,
        ClearAfter: false,
    }

    payloadBytes, err := json.Marshal(query)
    if err != nil {
        panic(err)
    }

    req, err := http.NewRequest("POST", baseURL+"/ptls", bytes.NewBuffer(payloadBytes))
    if err != nil {
        panic(err)
    }
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

    var ptls []PTLResponse
    err = json.Unmarshal(body, &ptls)
    if err != nil {
        panic(err)
    }

    for _, ptl := range ptls {
        if ptl.Unit == targetUnit {
            fmt.Printf("PTL Unit %d:\n", targetUnit)
            fmt.Printf("  Controller: %s\n", ptl.Controller)
            fmt.Printf("  State: %s\n", ptl.State)
            fmt.Printf("  Color: %s\n", ptl.Color)
            fmt.Printf("  Number: %d\n", ptl.Number)
            fmt.Printf("  Sub: %d\n", ptl.Sub)
            return
        }
    }

    fmt.Printf("PTL unit %d not found.\n", targetUnit)
}

Получение всех PTL, которые в данный момент активны

Под активным модулем имеется в виду модуль, у которого горит кнопка LED.

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

type PTLQuery struct {
    IP         string `json:"ip"`
    ClearAfter bool   `json:"clear_after"`
    Mode       string `json:"mode,omitempty"`
}

type PTLResponse struct {
    Unit       int    `json:"unit"`
    Controller string `json:"controller"`
    State      string `json:"state,omitempty"`
    Color      string `json:"color,omitempty"`
    Number     int    `json:"number,omitempty"`
    Sub        int    `json:"sub,omitempty"`
}

func main() {
    baseURL := "http://localhost:8000"     // Заменить на адрес API
    controllerIP := "192.168.0.100"         // Заменить на IP контроллера

    query := PTLQuery{
        IP:         controllerIP,
        ClearAfter: false,
        Mode:       "activated",
    }

    payloadBytes, err := json.Marshal(query)
    if err != nil {
        panic(err)
    }

    req, err := http.NewRequest("POST", baseURL+"/ptls", bytes.NewBuffer(payloadBytes))
    if err != nil {
        panic(err)
    }
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

    var ptls []PTLResponse
    err = json.Unmarshal(body, &ptls)
    if err != nil {
        panic(err)
    }

    fmt.Println("Activated PTLs:")
    for _, ptl := range ptls {
        fmt.Printf("  Unit: %d | Controller: %s | State: %s | Color: %s | Number: %d | Sub: %d\n",
            ptl.Unit, ptl.Controller, ptl.State, ptl.Color, ptl.Number, ptl.Sub)
    }
}

Отправка зажигания и цикличная обработка активных модулей


package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

type Command struct {
    Unit   int    `json:"unit"`
    Number int    `json:"number"`
    Sub    int    `json:"sub"`
    Color  string `json:"color"`
    Role   string `json:"role"`
}

type ControllerCommands struct {
    ControllerIP string    `json:"controller_ip"`
    Commands     []Command `json:"commands"`
}

type PTLQuery struct {
    IP         string `json:"ip"`
    ClearAfter bool   `json:"clear_after"`
    Mode       string `json:"mode"`
}

type PTLResponse struct {
    Unit int `json:"unit"`
}

func main() {
    apiURL := "http://localhost:8000"
    controllerIP := "192.168.0.100"

    var allUnits []int
    for i := 1; i <= 100; i++ {
        allUnits = append(allUnits, i)
    }

    batchSize := 10
    for i := 0; i < len(allUnits); i += batchSize {
        end := i + batchSize
        if end > len(allUnits) {
            end = len(allUnits)
        }
        batch := allUnits[i:end]

        sendTurnOn(apiURL, controllerIP, batch)
        waitForDeactivation(apiURL, controllerIP)
    }
}

func sendTurnOn(apiURL, controllerIP string, units []int) {
    var commands []Command
    for _, unit := range units {
        commands = append(commands, Command{
            Unit:   unit,
            Number: unit,
            Sub:    0,
            Color:  "Green",
            Role:   "worker",
        })
    }

    payload := ControllerCommands{
        ControllerIP: controllerIP,
        Commands:     commands,
    }

    body, err := json.Marshal(payload)
    if err != nil {
        panic(err)
    }

    resp, err := http.Post(apiURL+"/turn_on", "application/json", bytes.NewReader(body))
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    fmt.Printf("Turned on units: %v\n", units)
}

func waitForDeactivation(apiURL, controllerIP string) {
    for {
        active := getActivatedPTLs(apiURL, controllerIP)
        if len(active) == 0 {
            fmt.Println("All PTLs deactivated, moving to next batch.")
            return
        }
        fmt.Printf("Waiting, %d PTLs still active...\n", len(active))
        time.Sleep(2 * time.Second)
    }
}

func getActivatedPTLs(apiURL, controllerIP string) []PTLResponse {
    query := PTLQuery{
        IP:         controllerIP,
        ClearAfter: false,
        Mode:       "activated",
    }

    body, err := json.Marshal(query)
    if err != nil {
        panic(err)
    }

    resp, err := http.Post(apiURL+"/ptls", "application/json", bytes.NewReader(body))
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    respBody, _ := ioutil.ReadAll(resp.Body)

    var ptls []PTLResponse
    err = json.Unmarshal(respBody, &ptls)
    if err != nil {
        panic(err)
    }

    return ptls
}