Необходимо было сопряжение фискального регистратора(ФР) Штрих.. - установка времени компьютера на фискальном регистраторе - пришлось общаться с ФР с помощью команд в шестнадцатеричном формате. Перевод из десятичного формата в шестнадцатеричный нашел - http://infostart.ru/public/83824/, а обратно нет, пришлось написать. И вот что получилось
Функция ПеревестиЧислоИзШестнадцатиричногоВДесятичное(СтрокаХекс) Экспорт
На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.
При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.
Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.
Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)
Функция ШестнадцатиричноеВДесятичное(Источник) Экспорт
Результат = 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",
ВходныеПараметры,
ВыходныеПараметры);
КонецПроцедуры