|
Отправлено: 21.01.17 19:28. Заголовок: Добрый вечер! Попроб..
Добрый вечер! Попробую написать доку, заодно сам доразберусь что не потрогал)
Гид по кодировкам в современном SIMPL/S+ на 3-Series Чуть-чуть теории о кодировках и их хранении Windows-1251. Исторически примерно у всех (даже у китайцев) были 1-байтовые национальные кодировки, и сейчас у нас используется Windows-1251 как «Язык системы» (она выбирается в Control Panel – Region and Language – Administrative – Language for Non-Unicode programs (system locale) и называется там Russian(Russia)). В этой кодировке печатные символы имеют коды от 32 (0x20) до 255 (0xFF) и хранят эти символы традиционно по одному байту на символ. Для примера, символ Ы в ней имеет код 219 (0xDB). Кодировок полно, даже с кириллицей штук 5 вспомню, поэтому так вот имея строку и не зная её кодировки не сразу догадаешься что в неё написано. Unicode. Когда всех это поддостало, сделали Unicode, «всеобщую» кодировку где для каждого мыслимого символа есть по коду и много чего ещё. Сейчас в Unicode 9.0 использовано 271792 кода из заложенных в ней 1114112, и символ Ы в ней имеет код 1067 (0x042B). Выходило, что для хранения этих символов требовалось по 4 байта, и жадность человеческая привела к нескольким способам хранения, из которых сейчас все привыкли к UTF-8, довольно изощрённому, с переменным количеством байт для разных символов. Crestron традиционно не угадал тренд и выбрал UTF-16LE – вариант где каждый символ занимает по 2 байта, причём сначала хранится (или передаётся при потоковой передаче) старший байт. Что случается со строками в SIMPL/SIMPL+ Таки-да, ВНУТРИ SIMPL и SIMPL+ в 3-Series строки действительно состоят из 16-битных символов. Функция LEN() и String Length (SLEN) выдают именно количество символов в строке (а не её размер в байтах, например). Действительно, каждый символ может иметь код в диапазоне 0..65535, и в SIMPL+ можно его узнать с помощью функции – правильно: BYTE(), ну не зайки ли?) С младшими 8-ю битами (low byte) всё осталось как было в 2-Series, теперь расскажу что со старшими: В SIMPL строки введённые в параметры НЕ конвертируются, каждый символ там (после раскрытия всяких макроподстановок) точнёхонько попадает кодом в младший байт, кроме конструкции \u. В SIMPL можно получить символы с кодами >255 двумя способами: написав код в параметре в форме \u (например, \u042B будет Ы в Unicode) и получив строку c такими кодами из SIMPL+. В SIMPL можно передать символы с кодами >255 только в модуль SIMPL+. Никакие символы в SIMPL не работают со СТАРШИМИ байтами кода символа, они не передаются в потоках (по rs232 или через TCP/IP клиент), не проходят сквозь Intersystem Communications и CrossPoints, нет символов SIMPL их анализирующих в духе Serial to Analog, даже панели Crestron их не получат. Если вам требуется передать строку 16-битных символов между модулями SIMPL+, то это нужно делать явно, связав их одним сигналом. В отличие от SIMPL, в S+ константные строки в 3-Series преобразуются в Unicode. Сам файл USP считается написанным в кодировке «Языка системы» (обычно это Windows-1251), и S="Ы"; породит строку из одного символа с кодом 0x042B. Там так же можно использовать \u042В – получится то же самое. А вот чтобы сделать надпись с Ы в SIMPL+ 3-Series для старой панели (куда нужно передать строку в Windows-1251) придётся задать явно \xDB, или воспользоваться конвертором UTF16->WIN1251 (это как раз та разница, на которую попал автор поста!). В SIMPL+ ещё можно получить символы с кодами >255 из SIMPL или из параметров. Но я не знаю способа «сделать» символ по коду, CHR() делает символа только в 0..255, и никакой арифметики с ними нет – если вдруг знаете, поделитесь, битте) Представление строк в 3-Series: три большие разницы В 3-Series SIMPL Debugger показывает строки весьма замысловатым образом: от каждого символа берётся сначала старший байт (если он не 0), затем младший байт, потом то же самое со следующим символом и всё это вместе склеивается в колбасу, которую Debugger показывает в соответствии с Display Format. По этому виду можно довольно смутно догадываться какая там была строка, например показанное как \xDB\x04\x2B может быть строкой из трёх символов \u00DB\u0004\u002B, а может быть строкой из двух символов \u00DB\u042B или \uDB04\u002B – не угадаешь. TRACE() и PRINT() по шаблону %s в SIMPL+ символы с кодами 1..255 отображают по языку системы, т.е. в Windows-1251, код 0 обрывает строку, а символы с кодами >255 отображаются знаком вопроса, тоже не очень понятно. В общем, чтобы более-менее внятно выяснить что там сейчас в строке в S+ нужно конструкцию типа for( i=1 to len(s) ) makestring( desc, "%s\\x%X", desc, byte(s, i) ); и потом это гнать в trace(). Про конвертирование Параметры и строки в SIMPL и SIMPL+ имеют что-то вроде атрибута ASCII/UTF16, и в обеих средах есть прорва функционала, оперирующего с ним и конвертирующего сами строки. Это всё лажа к нам не имеющая отношения, их ASCII это Windows-1252, совсем без кириллицы. Пока не вызываются их конвертирующие функции этот атрибут ни на что не влияет. Варианты конверторов В общем смысле задача конвертирования состоит в превращении входного потока в выходной с какими-то условиями: • В какой кодировке идёт входящий поток (или строка). Это может быть Windows-1251, OEM(DOS) CP-866, MAC-Cyrillic, ISO 8859-5, IBM EBCDIC Cyrillic или Unicode. • Если Unicode, то важно как коды размещены в строке – с использованием старшего байта символа (как вышло у автора поста) или в только в младших байтах. Если в младших – то каким образом размещено в потоке – в UTF-8, UTF-16GE или UTF-16LE • То же на выход: скорее всего нужно делать строку только в младшие байты, нужно понять в какую кодировку, если Unicode – то в каком порядке. Или если вдруг всё это нужно показывать в SmartGraphics, куда текст вставляется в тело HTML, то там нужно делать подстановки в HTML character entity references, скажем Ы представляется как Ы или Ы Что было в 2-Series С 2-Series разговор короткий: совершенно везде внутри контроллера строки только с 1-байтовыми символами, никаких преобразований в/из Unicode нет и сам контроллер совершенно не догадывается в какой именно кодировке вы писали вашу программу, от этого никак не зависит его работа. Кириллица станет видна вам уже снаружи - в SIMPL Debugger, если system locale русская; на «старых» панелях – если в диалоге выбора шрифта для этого объекта с Indirect Text выбрать в Script значение Cyrillic (и какой дебил догадался переименовать?); на панели со Smart Graphics – если вы преобразовали кириллицу в HTML character entity references. SIMPL+ в 2-Series ничего не конвертирует в константных строках – как оно есть в файле USP, так и окажется в ELF. UPD: ограничения по длинам в 3-й серии и как передать длинный текст с кириллицей в SmartGraphics В 3-й серии в SIMPL+ можно делать строки до 65534 символов, однако наружу в SIMPL выйдет только 1024 из них, похоже это ограничение длины строки в SIMPL. Если этот выход НАПРЯМУЮ передать в SIMPL+ или на панель SmartGraphics (хоть бы и Crestron App), то строка придёт целиком (до 1024 символов), а если на пути было что угодно, хоть Serial Buffer то она скорее всего будет урезана до 255 символов и старшие байты символов будут обнулены. Есть ещё ограничение длины Indirect Text в SmartGraphics - 1017 символов. Неважно, указали вы join явно как Indirect/Append/Prepend Text Serial Join или уже в строке как CIP tag, строки более 1017 символов будут проигнорированы. Если в объекте нет Append Text Serial Join или вы используете форматирование со вставками через CIP tegs, всё-таки ещё есть способ сделать "длинную" строку: если перед пересылаемым текстом добавить \xFE\x02, то он не заменит предыдущую строку, а приклеится к ней, как поступает Append Text Serial Join - так можно передавать длинную строку порциями, я не обнаружил очевидного ограничения набираемого таким образом текста. Про другие префиксы, вызывающие стирание проекта или прошивки и MAC-адреса, а так же дым и искры на устройствах со SmartGraphics (как TSW x50, x52, x60 так и на iOS) напишу в следующий раз. UPD2: nonvolatile string Оказалось, что в nonvolatile string после перезагрузки все символы с кодом больше 255 превращаются в тыкву в "?", поэтому если что-то нужно вспомнить - по любому нужно перепаковывать в 1-байтовые строки.
|