Управление поворотным устройством для камеры видеонаблюдения

Здравствуйте.
Прошу помочь настроить управление поворотным устройством PTS-303Z через веб-gui WirenBoard 8. Поворотка использует протокол Pelco-D через RS-485.
Схема подключения: WB-8 → WB-MGE v.2 - > (WB-MR6LV/S+PTS-303Z).

Добрый день
К сожалению данное устройство мы не тестировали и у нас нет подробной настройки.
По схеме из интернета видно что устройство может быть подключено по RS-485, для данного устройства потребуется написать шаблон.
С помощью DIP переключателей формируется адрес устройства и его скорость на шине
Рекомендую сначала настроить устройство с контроллером, отладить шаблон, после уже подключить через преобразователь интерфейсов WB-MGE v.2.

Ещё порекомендую задать вопрос в нашем открытом сообществе телеграм, возможно кто то уже написал шаблон и любезно поделится опытом.
Но необходимо учитывать что наши устройства поддерживают протокол Modbus что для вашего случая может быть затруднительно напрямую, придется использовать какой то конвертер.

Вряд ли тут шаблон поможет.
Вижу упоминание Pelcod
То есть интерфейс 485 но протокол - не Modbus.

Описать можно через RPC вызовы, например Привод штор AT6501 - #6 от пользователя aho

Могу примерчик набросать с командой. Какую реализовать?

3 лайка

Могу примерчик набросать с командой. Какую реализовать?

буду очень признателен. Команду - да в общем то любую. к примеру “поворачивай налево пока жму кнопку поворота”

Вот реализация, проверьте пожалуйста

// Путь к RPC
var pathRPC = "/rpc/v1/wb-mqtt-serial/port/Load/";

/*
Из мануала:
Byte 1	Byte 2	Byte 3	Byte 4	Byte 5	Byte 6	Byte 7
Sync	Camera Address	Command 1	Command 2	Data 1	Data 2	Checksum
 

Byte 1 (Sync) - the synchronization byte, fixed to FF
Byte 2 (Camera Address) - logical address of the camera being controlled (Address 1 is 01)
Byte 3 & 4 (Command 1 and 2) are shown below
Byte 5 (Data 1) - pan speed, range from 00 (stop) to 3F (high speed) and FF for "turbo" speed (the maximum pan speed that the device can go)
Byte 6 (Data 2) - tilt speed, range from 00 (stop) to 3F (maximum speed)
Byte 7 (Checksum) - sum of bytes (excluding the synchronization byte), then modulo 100 (Decimal code: 256)

То есть длинfа посылки всегда 7 байт.
Первый - всегда 0xff
Второй - camID
3-4 команда
5 - скорость горизонталь
6 - скорость вертикаль
7 - crc. Вот его и реализуем в функции calcCRC
*/


// Вычисляет контрольную сумму CRC по протоколу Pelco-D
//На входе строка в которой каждый байт соответствует посылке. Если в строке есть 7 байт или больше они должны быть нулевыми.
function calcCRC(str) {
    // Сумма начинается с 0
    var sum = 0;

    // Проходим по строке, игнорируя первый символ (FF)
    for (i = 1; i < str.length; i++) {
        // Получаем числовое представление текущего символа (ASCII-код)
        var byteValue = str.charCodeAt(i);
        sum += byteValue;
    }

    // Возвращаем остаток от деления суммы на 256 
    //return (sum % 256).toString(16);
    return (sum % 256);
}

/*
//просто тест для CRC
var testStr = String.fromCharCode(0xff) +
                String.fromCharCode(0x10) +
                String.fromCharCode(0xf0) +
                String.fromCharCode(0x80) +
                String.fromCharCode(0x20) +
                String.fromCharCode(0x20) +
                String.fromCharCode(0x00);

log.info("calcCRC()", calcCRC(testStr)); //0xc0 норм
*/


function bytesToHexString(arr) {
    var result = '';
    for (var i = 0; i < arr.length; i++) {
        var hex = arr.charCodeAt(i).toString(16);
        //var hex = arr.charCodeAt(i);
      log.info("hex", i, "=", hex)
        if (hex.length < 2) {
            hex = '0' + hex;
        }
        result += hex;
    }
    return result;
}

function hexStringToBytes(hex) {
    var bytes = [];
    for (var i = 0; i < hex.length; i += 2) {
        bytes.push(parseInt(hex.substr(i, 2), 16));
    }
    return bytes;
}



function createCam(nameCam, portCam, speedportCam, parityCam, stopBitCam, camID) {
  //log.info ("nameCam=", nameCam )
  //log.info ("portCam=", portCam )
  //log.info ("speedportCam=", speedportCam )
  //log.info ("parityCam=", parityCam )
  //log.info ("stopBitCam=", stopBitCam )
  //log.info ("camID=", camID )
    // Создаем виртуальное устройство
    makeNewVirtualControl(nameCam, "panSpeed", { type: "range", value: 20, min: 0, max: 100, readonly: false });
    makeNewVirtualControl(nameCam, "Left", { type: "pushbutton", readonly: false });
    //makeNewVirtualControl(nameCam, "Up", { type: "pushbutton", readonly: false });
    //makeNewVirtualControl(nameCam, "Stop", { type: "pushbutton", readonly: false });
    //makeNewVirtualControl(nameCam, "Down", { type: "pushbutton", readonly: false });

    // Up
    defineRule(nameCam + "_rule", {
        whenChanged: nameCam + "/Left",
        then: function (newValue, devName, cellName) {
            log.info(nameCam + "RULE!", "cellName=", cellName);
            var req = camCommandMsg(camID, 0x00, 0x04, dev[nameCam+"/panSpeed"], 0x00);
            log.info("Left=", req);
            requestRPC(portCam, speedportCam, parityCam, stopBitCam, nameCam, 1, "HEX", req, 8);
        }
    });


/*
    // Position slider
    defineRule(nameCam + "_rule_position", {
        whenChanged: nameCam + "/Position",
        then: function (value) {
            var is_auto_set = positionSetAuto[camID];
            if (is_auto_set === 0) {
                //var val = (dev[nameCam] && dev[nameCam]["Position"] !== undefined) ? dev[nameCam]["Position"] : 0;
                //var req = camCommandMsg(camID, blindCh_L, blindCh_H, 0x03, 0x04, val);
                //requestRPC(portCam, speedportCam, parityCam, stopBitCam, nameCam, 1, "HEX", req, 8);
            } else {
                //positionSetAuto[camID] = 0;
            }
        }
    });
*/
  
    // MQTT reply tracking
    trackMqtt(pathRPC + nameCam + "/reply", function (message) {
        log.info("from " + nameCam + " name: {}, value: {}".format(message.topic, message.value));
        var replyObj;
        try {
            replyObj = JSON.parse(message.value);
        } catch (e) {
            log.error("JSON parse error: " + e);
            return;
        }
        if (replyObj && replyObj.error === null) {
            var hexStr = replyObj.result.response;
            log.info("from " + nameCam + " replyObj.result.response: {}".format(hexStr));
            }
        })
   
 
return 0;
}

function requestRPC(modbusPort, modbusSpeed, modbusParity, reqStopbit, clientID, requestID, messageType, message, responseSize) {
    // Формируем JSON запрос:
    var strJson = JSON.stringify({
        params: {
            response_size: responseSize,
            format: messageType,
            path: modbusPort,
            baud_rate: modbusSpeed,
            parity: modbusParity,
            data_bits: 8,
            stop_bits: reqStopbit,
            msg: message
        },
        id: requestID
    });
    publish(pathRPC + clientID, strJson, 2, false);
}

function camCommandMsg(camID, command1, command2, data1, data2) {
    // Сформируем набор байт команды строкой.
    var data = String.fromCharCode(0xFF, camID, command1, command2, data1, data2)
    log.info ("datalen=",data.length)

    var crc = calcCRC(data);//Рассчитаем CRC
    //log.info ("crc=",crc)
    //log.info ("dataHEX1=",data)
    data = data+String.fromCharCode(crc); //Добавим CRC к строке
    var bytesStr = bytesToHexString(data);
    //log.info ("dataHEX2=",data)
    return bytesStr;
}

function makeNewVirtualControl(vdName, nameControl, typeControl) {
    if (getDevice(vdName) === undefined) {
        log.info("Define new");
        defineVirtualDevice(vdName, {
            title: vdName,
            cells: {},
        });
    }
    // Проверим есть ли уже контрол и если нет - создадим.
    var devObj = getDevice(vdName);
    if (devObj && !devObj.isControlExists(nameControl)) {
        log.debug("Контрола " + nameControl + " нет, создаем.");
        devObj.addControl(nameControl, typeControl);
    }
}

// Создаем виртуальное устройство, с контролами для камеры
// ID делаем уникальным
// createCam(nameCam, portCam, speedportCam, parityCam, stopBitCam, camID)
//            имя               порт     bod parity stopbit  camID
createCam("Камера1", "/dev/ttyRS485-2", 9600, "N",    1,     0x01 );
1 лайк

Удалось ли проверить?