Необходимо было сопряжение фискального регистратора(ФР) Штрих.. - установка времени компьютера на фискальном регистраторе - пришлось общаться с ФР с помощью команд в шестнадцатеричном формате. Перевод из десятичного формата в шестнадцатеричный нашел - http://infostart.ru/public/83824/, а обратно нет, пришлось написать. И вот что получилось
Функция ПеревестиЧислоИзШестнадцатиричногоВДесятичное(СтрокаХекс) Экспорт
Порой необходимо временно отключить расширение 1С, не удаляя его, чтобы не потерять данные. Но в этом случае при каждом запуске всем будет лезть уведомление о неактивном расширении, хотя очевидно, это техническая информация, которой не стоит лишний раз пугать пользователей.
На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.
При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.
Функция ШестнадцатиричноеВДесятичное(Источник) Экспорт
Результат = 0;
ШеснадцатиричныеСимволы = "0123456789ABCDEF";
ДлинаСтроки = СтрДлина(Источник);
Для Поз = 1 По ДлинаСтроки Цикл
ИскомыйСимвол = Сред(Источник,Поз,1);
ЗначениеСимвола = Найти(ШеснадцатиричныеСимволы, ВРег(ИскомыйСимвол));
Если ЗначениеСимвола <=0 Тогда
#Если ТолстыйКлиентОбычноеПриложение Тогда
Сообщить("В числе обнаружен неверный символ: """ + ИскомыйСимвол+ """ ");
#КонецЕсли
Результат = 0;
Прервать;
Иначе
ЗначениеСимвола = ЗначениеСимвола - 1;
Результат = Результат + ЗначениеСимвола * Pow(16, ДлинаСтроки-Поз);
КонецЕсли;
КонецЦикла;
(9) kotich,
Вы сами то поняли, что сказали? :)
Смысл перегонять десятичные в шестнадцатиричные меньше 10 если они ОДИНАКОВЫ!
(1,2,3,4,5,6,7,8,9)
Достаточно из числа например 5, сделать строку "5".
:)
(10) bzmax, вы когда пишите код, добавляйте проверки. Например, если параметр не входит в диапазон, выдавайте предупреждение, а ещё лучше - вызывайте исключение. Поймите, когда данная функция вызывается в цикле для массива десятичных чисел, на выходе собирается , строка шестнадцатеричного представления, подобную ошибку в работе вашего кода отследить довольно трудно, в 15 случаях из 16 она отработает корректно. Для 1С это актуально в том случае, если она работает с внешними базами через уникальные идентификаторы объектов.
(16) Goruch,
Я пользовался драйвером для 1С: Из описания работы с ПО «ШТРИХ-М: Драйвер ФР» в соответствии с «требованиями к разработке драйверов для фискальных регистраторов» компании 1С:
Там нет функций установки даты и времени только через команды: DeviceControl(УправлениеУстройством) или DeviceControlHEX(УправлениеУстройствомХекс)
(18) Обычно для периферии сканеры штрих-кодов, ТСД, Весы для печати этикеток, различные пос приблуды лучше использовать драйвера или атолла или Штрих-М.
Иначе возни и мороки, как в вашем случае море.
Единственное, когда я писал выгрузку товаров из 1С Штрих-М Кассир в весы там пришлось серьезно возиться с 10<->16 системы исчисления. Так что не завидую.:)
1. Добавляете общий модуль "ФискальникиКлиент" - Только клиент, толстый клиент и внешнее соединение
Функция ТестОборудование(Оборудование, ПолныйЛог = Ложь) Экспорт
// Пишем лог
Лог = Формат(МенеджерОборудованияКлиентПереопределяемый.ДатаСеанса(),"ДЛФ=T") + " Имя команды: ТестУстройства" + Символы.ПС;
ВходныеПараметры = Неопределено;
ВыходныеПараметры = Неопределено;
ПараметрыУстройства = МенеджерОборудованияКлиентПовтИсп.ПолучитьПараметрыУстройства(Оборудование);
Результат = МенеджерОборудованияКлиент.ВыполнитьДополнительнуюКоманду("CheckHealth",
ВходныеПараметры,
ВыходныеПараметры,
Оборудование,
ПараметрыУстройства);
Если Не Результат Тогда
Попытка
ОписаниеОшибки = ВыходныеПараметры[1];
Исключение
ОписаниеОшибки = "";
КонецПопытки;
ОписаниеОшибки = "Тест не был пройден!" + Символы.ПС + ОписаниеОшибки;
РезНаОшибку = Новый Структура("Результат,ОписаниеОшибки,Лог",Ложь,ОписаниеОшибки,"");
Иначе
Если ПолныйЛог <> Истина Тогда
Возврат Неопределено;
КонецЕсли;
ОписаниеОшибки = "Команда выполнена успешно!"+(?(ВыходныеПараметры.Количество()>1, Символы.ПС+ВыходныеПараметры[1], ""));
РезНаОшибку = Новый Структура("Результат,ОписаниеОшибки,Лог",Истина,ОписаниеОшибки,"");
КонецЕсли;
// Пишем лог
Лог = Лог + Формат(МенеджерОборудованияКлиентПереопределяемый.ДатаСеанса(),"ДЛФ=T") + " " + ОписаниеОшибки + Символы.ПС +
"========================================" + Символы.ПС;
ОтветОтУстройства = Лог + ОтветОтУстройства;
РезНаОшибку.Лог = ОтветОтУстройства;
Возврат РезНаОшибку;
КонецФункции
//Объект - Структура вида: "Команда" (Команда в формате Хекс для ФР через пробелы "13 1E 00 00 00")
// и "КассаККМ" (КассаККМ - касса для отбора, функция доступна только для ФР)
Функция ВыполнитьКоманду(Объект, ФР, УникальИдент, РезультатПробитияЧека = Неопределено) Экспорт
Перем РезПечатиЧека;
РезПечатиЧека = Неопределено; //Нормальное состояние - чек не печатался, возможно просто нет Фискальника
Если ФискальникиСервер.ФискальныйРегистраторПоКассе(Объект.КассаККМ) = Истина Тогда
//
Если МенеджерОборудованияКлиент.ОбновитьРабочееМестоКлиента() Тогда // Проверка на определенность рабочего места ВО
Если ФР.Пустая() Тогда
ИдентификаторУстройства = МенеджерОборудованияКлиент.ВыбратьУстройство("ФискальныйРегистратор",
НСтр("ru='Выберите фискальный регистратор'"),
НСтр("ru='Фискальный регистратор не подключен'"));
Иначе
ИдентификаторУстройства = ФР;
КонецЕсли;
Если ИдентификаторУстройства <> Неопределено Тогда
РезТестаОборудования = ФискальникиКлиент.ТестОборудование(ИдентификаторУстройства);
Если РезТестаОборудования <> Неопределено Тогда
ТекстСообщения = НСтр("ru = 'При проверке устройства произошла ошибка. Команда не выполнена на фискальном регистраторе.
|Дополнительное описание:
|%ДополнительноеОписание%'");
ТекстСообщения = СтрЗаменить(ТекстСообщения, "%ДополнительноеОписание%", РезТестаОборудования.Лог);
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
РезПечатиЧека = -5; //Число, код ошибки...
Возврат РезПечатиЧека;
КонецЕсли;
// Подключаем ФР
ОписаниеОшибки_ = "";
Результат = МенеджерОборудованияКлиент.ПодключитьОборудованиеПоИдентификатору(УникальИдент,
ИдентификаторУстройства,
ОписаниеОшибки_);
Если Результат Тогда
// Готовим данные
ВходныеПараметры = Новый Массив;
ВыходныеПараметры = Неопределено;
ВходныеПараметры.Добавить(Объект.Команда);
// Выполняем команду.
Попытка
Результат = МенеджерОборудованияКлиент.ВыполнитьКоманду(
ИдентификаторУстройства,
"DeviceControlHEX",
ВходныеПараметры,
ВыходныеПараметры);
Исключение
СтрОписОшибки = ОписаниеОшибки();
Если ТипЗнч(ВыходныеПараметры) <> Тип("Массив") Тогда
ВыходныеПараметры = Новый Массив;
КонецЕсли;
КолМасс = ВыходныеПараметры.Количество();
Для Сч = КолМасс По 4 Цикл
ВыходныеПараметры.Добавить(Неопределено);
КонецЦикла;
ВыходныеПараметры[0] = 999;
ВыходныеПараметры[1] = "Вызвыно Исключение ""ВыполнитьКоманду""";
ВыходныеПараметры[3] = СтрОписОшибки;
Результат = Ложь;
КонецПопытки;
// Отключаем ФР
МенеджерОборудованияКлиент.ОтключитьОборудованиеПоИдентификатору(УникальИдент,
ИдентификаторУстройства);
Если Результат Тогда
// Установить полученное значение номера чека реквизиту документа.
РезПечатиЧека = 1; //Число, Положительный, все замечательно
Иначе
ТекстСообщения = НСтр("ru = 'При выполнении команды произошла ошибка. Команда не выполнена на фискальном регистраторе.
|Дополнительное описание: %ДополнительноеОписание%'");
ТекстСообщения = СтрЗаменить(ТекстСообщения,
"%ДополнительноеОписание%",
ВыходныеПараметры[1]);
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
РезПечатиЧека = -1; //Число, код ошибки...
КонецЕсли;
Если РезультатПробитияЧека = Неопределено Тогда
РезультатПробитияЧека = Новый Структура;
КонецЕсли;
РезультатПробитияЧека.Вставить("КодОшибки",ВыходныеПараметры[0]);
РезультатПробитияЧека.Вставить("Расшифровка",ВыходныеПараметры[1]);
РезультатПробитияЧека.Вставить("ВыхДанные",ВыходныеПараметры[2]);
РезультатПробитияЧека.Вставить("ОписаниеОшибки",ВыходныеПараметры[3]);
Иначе
ТекстСообщения = НСтр("ru = 'При подключении устройства произошла ошибка. Команда не выполнена на фискальном регистраторе.
|Дополнительное описание: %ДополнительноеОписание%'");
ТекстСообщения = СтрЗаменить(ТекстСообщения, "%ДополнительноеОписание%", ОписаниеОшибки_);
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
РезПечатиЧека = -2; //Число, код ошибки...
КонецЕсли;
Иначе
ТекстСообщения = НСтр("ru = 'Не выбран фискальный регистратор.'");
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
РезПечатиЧека = -3; //Число, код ошибки...
КонецЕсли;
Иначе
ТекстСообщения = НСтр("ru = 'Предварительно необходимо выбрать рабочее место внешнего оборудования текущего сеанса.'");
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
РезПечатиЧека = -4; //Число, код ошибки...
КонецЕсли;
ИначеЕсли ФискальникиСервер.ФискальныйРегистраторПоКассе(Объект.КассаККМ) = Ложь Тогда
//Это обычная касса, или Чекопичатающая машинка...
Если РезультатПробитияЧека = Неопределено Тогда
РезультатПробитияЧека = Новый Структура;
КонецЕсли;
РезультатПробитияЧека.Вставить("ПровестиДокумент",Истина);
КонецЕсли;
Возврат РезПечатиЧека;
КонецФункции
Показать
2. Добавляете общий модуль "ФискальникиСервер"
Функция Из_10_В_Любую(Знач Значение=0,Нотация=36) Экспорт
Если Нотация<=0 Тогда Возврат("") КонецЕсли;
Значение=Число(Значение);
Если Значение<=0 Тогда Возврат("0") КонецЕсли;
Значение=Цел(Значение);
Результат="";
Пока Значение>0 Цикл
Результат=Сред("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",Значение%Нотация+1,1)+Результат;
Значение=Цел(Значение/Нотация) ;
КонецЦикла;
Возврат Результат;
КонецФункции
//_________________________________________________________
Функция Из_Любой_В_10(Знач Значение="0",Нотация=36) Экспорт
Если Нотация<=0 Тогда Возврат(0) КонецЕсли;
Значение=СокрЛП(Значение);
Если Значение="0" Тогда Возврат(0) КонецЕсли;
Результат=0;
Длина=СтрДлина(Значение);
Для Х=1 По Длина Цикл
М=1;
Для У=1 По Длина-Х Цикл М=М*Нотация КонецЦикла;
Результат=Результат+(Найти("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",Сред(Значение,Х,1))-1)*М;
КонецЦикла;
Возврат Окр(Результат);
КонецФункции
//Сообщил Рупор Абсурда (avb).
Функция ПеревестиЧислоИз16в10(СтрокаХекс) Экспорт
Возврат Из_Любой_В_10(СтрокаХекс, 16);
КонецФункции
Функция ПеревестиЧислоИз10в16(Число, Байт = Неопределено, НулиСправа = Истина) Экспорт
ЧислВ16 = Из_10_В_Любую(Число, 16);
Если Байт <> Неопределено и Байт > 0 Тогда
//Допишем нулики, не достающие...
пКолСимв = Байт * 2; //1 байт = 2 символам
//Подставим недостающие нули
СтДлин = СтрДлина(ЧислВ16);
Если СтДлин = 0 Тогда
//Заполним нулями
Для Сч = 1 По Байт Цикл
ЧислВ16 = ЧислВ16 + "00";
КонецЦикла;
ИначеЕсли СтДлин % 2 <> 0 Тогда
//Если нехватает одного нулика
ЧислВ16 = "0" + ЧислВ16;
КонецЕсли;
//Проверем на избыток
СтДлин = СтрДлина(ЧислВ16);
Если СтДлин > пКолСимв Тогда
ЧислВ16 = "";
Для Сч = 1 По Байт Цикл
Если НулиСправа = Истина Тогда
ЧислВ16 = ЧислВ16 + "00";
Иначе
ЧислВ16 = "00" + ЧислВ16;
КонецЕсли;
КонецЦикла;
Иначе
//Добъем просто нулями до кондиции!!!
Для Сч = СтДлин+1 По пКолСимв Цикл
Если НулиСправа = Истина Тогда
ЧислВ16 = ЧислВ16 + "0";
Иначе
ЧислВ16 = "0" + ЧислВ16;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Иначе
//Подставим недостающие нули
СтДлин = СтрДлина(ЧислВ16);
Если СтДлин % 2 <> 0 Тогда
//Если нехватает одного нулика
ЧислВ16 = "0" + ЧислВ16;
КонецЕсли;
КонецЕсли;
Возврат ЧислВ16;
КонецФункции
//В конец и в начале пробелы сокращатся
Функция МеждуДвумяСимволамиПробел(Число16) Экспорт
пЧисло16 = СокрЛП(Число16);
СтрДлин = СтрДлина(пЧисло16);
КолРаз = Цел(СтрДлин/2);
Если КолРаз <> (СтрДлин/2) Тогда
КолРаз = КолРаз + 1;
КонецЕсли;
Сч = 1;
Если Сч <= КолРаз Тогда
РезпЧисло16 = "";
Сч_ = 1;
Пока Сч <= КолРаз Цикл
Симв = Сред(пЧисло16,Сч_,2);
РезпЧисло16 = РезпЧисло16 + Симв + " ";
Сч = Сч + 1;
Сч_ = Сч_ + 2;
КонецЦикла;
Иначе
РезпЧисло16 = пЧисло16;
КонецЕсли;
Возврат СокрЛП(РезпЧисло16);
КонецФункции
Функция УбратьПробелы(Число16) Экспорт
Возврат СтрЗаменить(Число16," ","");
КонецФункции
Функция ПеревернутьСтроку(СтрокаХекс, ПараСимв = 1) Экспорт
СтрДлин = СтрДлина(СтрокаХекс);
пСтрокаХекс = "";
Сч = 1;
Пока Сч <= СтрДлин Цикл
СледСимв = Сред(СтрокаХекс,Сч, ПараСимв);
СледСимв = ДополнитьСтрокуСправа(СледСимв, ПараСимв, " ");
пСтрокаХекс = СледСимв + пСтрокаХекс;
Сч = Сч + ПараСимв;
КонецЦикла;
Возврат СокрЛП(пСтрокаХекс);
КонецФункции
Функция ДополнитьСтрокуСправа(СтрокаСимв, КолСимволов, СимволДоп) Экспорт
КолСимвВсего = СтрДлина(СтрокаСимв);
Если КолСимвВсего < КолСимволов Тогда
пСтрокаСимв = СтрокаСимв;
Для Сч = КолСимвВсего+1 По КолСимволов Цикл
пСтрокаСимв = пСтрокаСимв + СимволДоп;
КонецЦикла;
Возврат пСтрокаСимв;
Иначе
Возврат СтрокаСимв;
КонецЕсли;
КонецФункции
Функция ДополнитьСтрокуСлева(СтрокаСимв, КолСимволов, СимволДоп) Экспорт
КолСимвВсего = СтрДлина(СтрокаСимв);
Если КолСимвВсего < КолСимволов Тогда
пСтрокаСимв = СтрокаСимв;
Для Сч = КолСимвВсего+1 По КолСимволов Цикл
пСтрокаСимв = СимволДоп + пСтрокаСимв;
КонецЦикла;
Возврат пСтрокаСимв;
Иначе
Возврат СтрокаСимв;
КонецЕсли;
КонецФункции
Показать
3. В общем модуле модуле "ПодключаемоеОборудованиеШтрихМФискальныеРегистраторыКлиент",
а. в функции "ВыполнитьКоманду", прописываете
// Передает низкоуровневую команду устройству
ИначеЕсли Команда = "УправлениеУстройствомХекс" ИЛИ Команда = "DeviceControlHEX" Тогда
КоманднаяСтрока = ВходныеПараметры[0];
Результат = УправлениеУстройствомХекс(ОбъектДрайвера, Параметры, ПараметрыПодключения, КоманднаяСтрока, ВыходныеПараметры);
б. добавляете туда же функцию:
Функция УправлениеУстройствомХекс(ОбъектДрайвера, Параметры, ПараметрыПодключения, КоманднаяСтрока, ВыходныеПараметры) Экспорт
Результат = Истина;
пВходныеПараметры = КоманднаяСтрока;
пВыходныеПараметры = "";
Попытка
ОписОшибки = "";
Результат = ОбъектДрайвера.DeviceControlHex(ПараметрыПодключения.ИДУстройства, пВходныеПараметры, пВыходныеПараметры);
Исключение
ОписОшибки = ОписаниеОшибки();
ОписОшибки = ОписОшибки + Символы.ПС + "Команда - ["+КоманднаяСтрока+"]";
Результат = Ложь;
КонецПопытки;
ВыходныеПараметры.Очистить();
Если НЕ Результат Тогда
ВыходныеПараметры.Добавить(999);
Иначе
ВыходныеПараметры.Добавить(0);
КонецЕсли;
ВыходныеПараметры.Добавить("");
ВыходныеПараметры.Добавить(пВыходныеПараметры);
ВыходныеПараметры.Добавить(ОписОшибки);
ВыходныеПараметры[0] = ОбъектДрайвера.ПолучитьОшибку(ВыходныеПараметры[1]);
Если ПустаяСтрока(ОписОшибки) Тогда
ВыходныеПараметры[3] = "Команда - ["+КоманднаяСтрока+"]";
КонецЕсли;
Возврат Результат;
КонецФункции
Показать
4. И далее указываете к примеру обращение к внутренним командам драйвера:
//Печать контрольной ленты
&НаКлиенте
Процедура ФР_КонтрольнаяЛента(Команда)
// Вставить содержимое обработчика.
Если ФР.Пустая() Тогда
ТекстСообщения = "Оборудование не выбрано!";
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
Возврат;
КонецЕсли;
Если НЕ ЕстьПравоНаПечатьКЛ_ФР() Тогда
ТекстСообщения = "Нет права доступа для печати ""Контрольной ленты по смене""!";
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
Возврат;
КонецЕсли;
ТекстВопроса = "Для печати Контрольной ленты необходимо указать:
|номер смены в интервале 0000…2100.
|
|Рапечатать Контрольную ленту по смене "+Строка(НомерСменыКЛ)+" ?";
РезОтвета = Вопрос(ТекстВопроса, РежимДиалогаВопрос.ДаНет, 30, КодВозвратаДиалога.Нет, "Вопрос...", КодВозвратаДиалога.Нет);
Если РезОтвета <> КодВозвратаДиалога.Да Тогда
Возврат;
КонецЕсли;
//СтрокаДляКонтрольнойЛенты
СтрокаДляКонтрольнойЛенты = "A6"; //1 байт, Команда для печати контрольной ленты
//Добавим пароль Администратора, 4 байта
ПарольСисАдмина = 30;
СтрокаПароляХекс = ФискальникиСервер.ПеревестиЧислоИз10в16(ПарольСисАдмина, 4, Ложь);
СтрокаПароляХекс = ФискальникиСервер.ПеревернутьСтроку(СтрокаПароляХекс,2);
СтрокаДляКонтрольнойЛенты = СтрокаДляКонтрольнойЛенты + СтрокаПароляХекс;
//Номер смены, 2 байта
СтрокаНомерСмены = ФискальникиСервер.ПеревестиЧислоИз10в16(НомерСменыКЛ, 2, Ложь);
СтрокаНомерСмены = ФискальникиСервер.ПеревернутьСтроку(СтрокаНомерСмены,2);
СтрокаДляКонтрольнойЛенты = СтрокаДляКонтрольнойЛенты + СтрокаНомерСмены;
//Допишем пробелы, и того 7 байт на команду, без учета пробелов... :)
СтрокаДляКонтрольнойЛенты = ФискальникиСервер.МеждуДвумяСимволамиПробел(СтрокаДляКонтрольнойЛенты);
//Сообщить(СтрокаДляКонтрольнойЛенты); //Отладка
// Подготовка данных ФР
ВходныеПараметры = Новый Массив;
ВходныеПараметры.Добавить(СтрокаДляКонтрольнойЛенты);
ВыходныеПараметры = Неопределено;
ВыполнитьКомандуОборудования(ФР,
"DeviceControlHEX",
ВходныеПараметры,
ВыходныеПараметры);
КонецПроцедуры