0
Answered

формирование OSC (OpenSoundControl) комманд ?

Ramil Vafin 5 years ago in Tips and Tricks updated by Aleksandr Romanov (CTO) 2 years ago 8
Как преобразовать значение из элемента Уровень (float32) в формат HEX ?
Т.е. мне нужно сформировать команду в формате OSC: /volume,f XX XX XX XX, где ХХ - это значение взятое из элемента Уровень в HEX формате. Диапазон значений от -40,00 до 12,00 (числа с плавающей запятой).

Answer

Answer
Answered
Добрый день, Ramil Vafin!

Это связано с отправкой данных в виде строки, требуется вместо этого сформировать массив байт значений.

var hex = IEEE754_DecToHEX(this.Value); 
// Конвертируем в массив байтов
var hexArray = [];
hexArray[0] = parseInt('0x' + hex.charAt(0) + hex.charAt(1), 16);
hexArray[1] = parseInt('0x' + hex.charAt(2) + hex.charAt(3), 16);
hexArray[2] = parseInt('0x' + hex.charAt(4) + hex.charAt(5), 16);
hexArray[3] = parseInt('0x' + hex.charAt(6) + hex.charAt(7), 16);

// Выводим в лог
IR.Log(hex);
IR.Log(hexArray);

var Packet = "/value"; // начало пакета
var end = "\r\n"; // конец пакета

hexArray.unshift(0x00); // Два символа нуля после начала пакета
hexArray.unshift(0x00);

hexArray.unshift(Packet); // Добавляем начало пакета
hexArray.push(end); // Добавляем конец пакета

// отправляем
IR.GetDevice("AV & Custom Systems (TCP)").Send(hexArray);




Answered
Здравствуйте, Рамиль

Число в НЕХ:

hexString = yourNumber.toString(16);
Обратно:

yourNumber = parseInt(hexString, 16);
Схожая реализация:
http://support.iridiummobile.net/topic/617968-send-command-to-av-driver-from-level-or-edit-box-item/



Предложенное решение не помогает, т.к. в протоколе OSC жесткие требования к размерности команды. Я дополнительно изучил требуемый диапазон, он лежит в диапазоне от 0,00000000 до 1,00000000, что в HEX выглядит как : 00 00 00 00 до 3F 80 00 00. Как быть ?
Кстати этот формат имеет свой стандарт - IEEE-754.

Answered
Добрый день, Ramil Vafin!

Судя из описания, похоже что интерпретация значения в число с плавающей точкой происходит на устройстве, поэтому приложению iRidium без разницы, как его будут на самом деле использовать. Задача сводится к тому, что бы отослать HEX символы из указанного диапазона.
1. Определим диапазон значений HEX на выходе от 00 00 00 00 до 3F 80 00 00, тоже самое в DEC от 0 до 1065353216.
2. Создадим элемент типа Level в GUI Editor с Range Type = Interger, Min = 0; Max = 1065353216;
3. Напишем метод конвертации числа из Dec to Hex
Так как отправляется 16-ая строка фиксированной длинны, важно учесть, что при стандартной конвертации числа, длинна не учитывается и это надо компенсировать.
// конвертация значения
function IEEE754_DecToHEX (dec) {      
   var hex = dec.toString(16); 
   var zeroCount = 7; 
   if (dec > 15) zeroCount--;                                   
   if (dec > 255) zeroCount--;              
   if (dec > 4095) zeroCount--;    
   if (dec > 65535) zeroCount--;    
   if (dec > 1048575) zeroCount--;    
   if (dec > 16777215) zeroCount--;    
   if (dec > 268435455) zeroCount--; 
   if (dec > 4294967295) zeroCount--;      
   
   hex = addZero(zeroCount, hex);
   return hex; 
}


// компенсация недостающих нулей
function addZero(count, string) {
   var stringZero = "";
   for (var i = 0; i < count; i++) {
      stringZero += "0";      
   }
   return stringZero + string; 
}
4. Обратимся к свойству Value уровня через скрипт в событии Release, выполним конвертацию и напечатаем результат в консоль отладки.

// Получение значения и вывод
function getValue (){   
   var hex = IEEE754_DecToHEX(this.Value);
   IR.Log(hex);   
}

// Получение доступа к элементу и подписка
var Item = IR.GetItem("Page 1").GetItem("Item 1");
Item.Min = 0;
Item.Max = 1065353216
IR.AddListener(IR.EVENT_ITEM_RELEASE, Item, getValue, Item);

Изучите следующий пример проекта.

Да в логе все выглядит хорошо, но когда я отправляю значение в устройство:

function getValue () {
var Packet = "/value";
var hex = IEEE754_DecToHEX(this.Value);
IR.Log(hex);
IR.GetDevice("UDPdrv").Send([Packet,0x00,0x00,0x00,0x00,hex]);
{
приходит следующее:
[/value] 00 00 00 00 33 66 38 30 30 30 30 30

а должно быть:
[/value] 00 00 3F 80 00 00
(на примере максимального значения уровня). Т.е. при отправке опять происходит преобразование. Чего делать не надо.

Answer
Answered
Добрый день, Ramil Vafin!

Это связано с отправкой данных в виде строки, требуется вместо этого сформировать массив байт значений.

var hex = IEEE754_DecToHEX(this.Value); 
// Конвертируем в массив байтов
var hexArray = [];
hexArray[0] = parseInt('0x' + hex.charAt(0) + hex.charAt(1), 16);
hexArray[1] = parseInt('0x' + hex.charAt(2) + hex.charAt(3), 16);
hexArray[2] = parseInt('0x' + hex.charAt(4) + hex.charAt(5), 16);
hexArray[3] = parseInt('0x' + hex.charAt(6) + hex.charAt(7), 16);

// Выводим в лог
IR.Log(hex);
IR.Log(hexArray);

var Packet = "/value"; // начало пакета
var end = "\r\n"; // конец пакета

hexArray.unshift(0x00); // Два символа нуля после начала пакета
hexArray.unshift(0x00);

hexArray.unshift(Packet); // Добавляем начало пакета
hexArray.push(end); // Добавляем конец пакета

// отправляем
IR.GetDevice("AV & Custom Systems (TCP)").Send(hexArray);