Comments 37
А не скажете, бывают ли такие устройства с wifi?
И еще, можно ли писать на C++ или VB.Net?
И еще, можно ли писать на C++ или VB.Net?
Конечно, на моем образце есть wifi. Мы организовали wifi сеть на складе с повторителями, таким образом все сканеры постоянно в режиме online, в одной сети (примерно 15 сканеров и 20 точек доступа). А приложение позволяет напрямую подключаться и считывать данные с базы данных (через веб-сервис).
Язык, на котором писать — особой роли не играет. EMDK так же есть отдельно для C++.
Язык, на котором писать — особой роли не играет. EMDK так же есть отдельно для C++.
Кстати, с помощью Symbol.WirelessLAN можно управлять WiFi приемником почти с такой же легкостью, как и сканером штрихкодов.
А это все уже устарело или только Symbol? Продаются такие железки сейчас и если да то сколько стоят?
Да, продают, и очень активно. В среднем от 15 000 до 180 000 рублей, в зависимости от характеристик. Что касается устаревания Symbol, я думаю, что это как-то связано с тем, событием, когда Google купила Motorola. Все новые терминалы сбора данных от Motorola выходят на андройде.
Motorola Solutions никак не связана с той Motorola, которую купил Google. Общего — только слово «Motorola».
А по поводу Андроида — ну а на чём их выпускать? На морально устаревших Windows CE/Mobile 6.5 и т.п.? Windows Phone Embedded ещё только грозятся выпустить. iOS не существует вне устройств Apple. А больше операционок-то и нет.
Мы купили Motorola TC55 на Android — отличная вещь.
И вообще, очень многие производители сейчас выпускают ТСД именно на Андроиде.
А по поводу Андроида — ну а на чём их выпускать? На морально устаревших Windows CE/Mobile 6.5 и т.п.? Windows Phone Embedded ещё только грозятся выпустить. iOS не существует вне устройств Apple. А больше операционок-то и нет.
Мы купили Motorola TC55 на Android — отличная вещь.
И вообще, очень многие производители сейчас выпускают ТСД именно на Андроиде.
Девайс выглядит очень аппетитно. Удобно ли вводить данные в перчатках? В спецификации указано, что экран емкостной, но понимает, когда на него нажимают в перчатках.
Обязательно постараюсь себе такой достать.
Обязательно постараюсь себе такой достать.
Какие преимущества у Motorola TC55 перед обычным защищенным смартфоном на андроиде с нормальной камерой?
как будет обновляться ПО в ТСД, в предложенной реализации?
Для начала стоит ответить на вопрос: «Для чего может потребоваться обновление?»
При работе с проектами, после завершения пилотного этапа, обновления, если и будут — то минимальны. Потому что подобные решения проектируются уже под бизнес-логику конкретного клиента, и если понадобится когда нибудь изменить сам порядок работы, то фактически придется прорабатывать проект заново, а потом уже вносить доработки в ПО. А все мелкие недочеты, оформление и «хотелки» решаются на пилотном этапе. Потому есть смысл ограничиться лишь запросом актуальности установленной версии, и блокировки работы, до последующего обновления вручную системным администратором.
В рабочих проектах вкладывать ресурсы на разработку самообновляющихся приложений имеет смысл только в случае работы над типовыми тиражируемыми продуктами. В этом случае, обычно, создается некий онлайн сервис, с помощью которого можно реализовать автозагрузку и установку новой версии приложения. Статей, о том как на C# реализовать подобное очень много.
При работе с проектами, после завершения пилотного этапа, обновления, если и будут — то минимальны. Потому что подобные решения проектируются уже под бизнес-логику конкретного клиента, и если понадобится когда нибудь изменить сам порядок работы, то фактически придется прорабатывать проект заново, а потом уже вносить доработки в ПО. А все мелкие недочеты, оформление и «хотелки» решаются на пилотном этапе. Потому есть смысл ограничиться лишь запросом актуальности установленной версии, и блокировки работы, до последующего обновления вручную системным администратором.
В рабочих проектах вкладывать ресурсы на разработку самообновляющихся приложений имеет смысл только в случае работы над типовыми тиражируемыми продуктами. В этом случае, обычно, создается некий онлайн сервис, с помощью которого можно реализовать автозагрузку и установку новой версии приложения. Статей, о том как на C# реализовать подобное очень много.
В каком-то идеальном проекте и идеальной организации может обновлять и не потребуется. Занимаюсь складской логистикой уже два года и изменения в бизнесс-процессах могут быть достаточно серьёзными (а несерьёзные изменения — частыми). А когда в организации несколько тысяч ТСД (разных моделей) разбросанных по разным складам, то их обновление очень нетривиальная задача. Никаких самообновляющихся приложений не используем. Веб сервисы и всё через браузер работает прекрасно.
Наш клиент написан на C# и эволюционно мы пришли к следующей схеме:
Клиент очень тонкий, не содержит бизнес-логики.
Клиент хранит состояние (произвольная строка, обычно XML, клиент эту строку не парсит).
После каждого действия пользователя (сканирование, нажатие клавиши) состояние отправляется на сервер вместе с действием пользователя, а приходит ответ — новое состояние и что нужно показать в UI.
UI включает несколько типовых форм (два Memo, или Grid+Memo, или MessageBox), полностью настраиваемых — можно передать текст футера, хидера, цвет и содержимое некоторых элементов, в т.к. сложных типа Grid, если операция подразумевает показ мини-отчёта.
Обновлять такой клиент нужно очень редко, только в случаях, когда необходимой формы ещё не было (например, ввод ШК вручную). Новые формы UI делаются максимально гибкими, чтобы их можно было переиспользовать для разных сценариев.
Клиент очень тонкий, не содержит бизнес-логики.
Клиент хранит состояние (произвольная строка, обычно XML, клиент эту строку не парсит).
После каждого действия пользователя (сканирование, нажатие клавиши) состояние отправляется на сервер вместе с действием пользователя, а приходит ответ — новое состояние и что нужно показать в UI.
UI включает несколько типовых форм (два Memo, или Grid+Memo, или MessageBox), полностью настраиваемых — можно передать текст футера, хидера, цвет и содержимое некоторых элементов, в т.к. сложных типа Grid, если операция подразумевает показ мини-отчёта.
Обновлять такой клиент нужно очень редко, только в случаях, когда необходимой формы ещё не было (например, ввод ШК вручную). Новые формы UI делаются максимально гибкими, чтобы их можно было переиспользовать для разных сценариев.
А вариант с браузерной версией рассматривался? Почему выбрали именно такой вариант реализации, какие преимущества? Экономия трафика, требовательность к железу, скорость разработки и т.д.?
Т.е. вы сделали браузер? :)
А как со скоростью работы? Ведь каждое сканирование обрабатывать на сервере — очень накладно и долго: пользователю надо отсканировать кучу штрихкодов, а он ждет 2-3 секунды после каждого…
А как со скоростью работы? Ведь каждое сканирование обрабатывать на сервере — очень накладно и долго: пользователю надо отсканировать кучу штрихкодов, а он ждет 2-3 секунды после каждого…
Откуда такой прогноз?
Даже далёкие филиалы в Москве получают ответ за 100-200ms, если операция — просто добавить ШК в «состояние» (и проверить, существует ли ШК в базе). Зато некоторый плюс — каждый штрих проверяется в онлайне, пользователь быстрее получает отклик.
Даже далёкие филиалы в Москве получают ответ за 100-200ms, если операция — просто добавить ШК в «состояние» (и проверить, существует ли ШК в базе). Зато некоторый плюс — каждый штрих проверяется в онлайне, пользователь быстрее получает отклик.
Время — всего лишь предположение. Плюсов у такого решения много, не спорю, но это накладывает жесткие ограничения на качество сети.
Теоретически можно представить сценарий, когда накопление ШК локально и отправка на сервер одним пакетом полезны.
Но на практике удобнее, чтобы каждый ШК проверялся он-лайн. Можно перепроверить наименование товара, вывести его на экран после сканирования. Особенно важно проверять перемещения и отгрузку. Если какой-то заказ не оплачен, сканер должен сразу выдать ошибку перемещения, не заставляя оператора потом искать среди 50 отсканированных позиций то, что надо вернуть.
Интересно, можно ли из браузера работать со спикером?
У нас есть разнообразная звуковая индикация ошибок и событий.
Но на практике удобнее, чтобы каждый ШК проверялся он-лайн. Можно перепроверить наименование товара, вывести его на экран после сканирования. Особенно важно проверять перемещения и отгрузку. Если какой-то заказ не оплачен, сканер должен сразу выдать ошибку перемещения, не заставляя оператора потом искать среди 50 отсканированных позиций то, что надо вернуть.
Интересно, можно ли из браузера работать со спикером?
У нас есть разнообразная звуковая индикация ошибок и событий.
Если использовать «документную» архитектуру, а не товарную, то проблем с локальной обработкой меньше: на ТСД приходит «документ», например заказ, который необходимо собрать. Тут мы четко знаем какие шк мы ждем от пользователя.
Со спикером — не готов точно ответить сейчас, но проигрывать локальные звуковые файлы — да. Так же можно взаимодействовать с клавиатурой ТСД, файловой системой, делать вызовы внешних программ с ожиданием их ответа и еще много всего. Немаловажно, что браузер блокирует систему: из него нельзя выйти (если в своей программе не поедусмотреть это)
Со спикером — не готов точно ответить сейчас, но проигрывать локальные звуковые файлы — да. Так же можно взаимодействовать с клавиатурой ТСД, файловой системой, делать вызовы внешних программ с ожиданием их ответа и еще много всего. Немаловажно, что браузер блокирует систему: из него нельзя выйти (если в своей программе не поедусмотреть это)
Расскажите поподробнее, что произойдет, если вы просканируете шк товара, которого нет в списке документа? Программа с этой архитектурой его просто не распознает?
Так же очень интересно, как вы работаете с такой архитектурой с упаковками, и весовым товаром. Ведь любому штрихкоду товара соответствует артикул и упаковка, в которой (т.е. и количество штук в упаковке) он лежит, если товар штучный, и артикул и его вес, если товар весовой.
Так же очень интересно, как вы работаете с такой архитектурой с упаковками, и весовым товаром. Ведь любому штрихкоду товара соответствует артикул и упаковка, в которой (т.е. и количество штук в упаковке) он лежит, если товар штучный, и артикул и его вес, если товар весовой.
Да, просто не распознает, а пользователю будет сообщение вроде «товара нет в документе».
С упаковкой и весом согласен, так не поработаешь. Но ведь мы выбираем решения в зависимости от целей :)
На данный момент бизнес-логика не предполагает таких операций, а если требования появятся, то в браузере тоже не составит труда сходить на сервер аяксом в любой момент
С упаковкой и весом согласен, так не поработаешь. Но ведь мы выбираем решения в зависимости от целей :)
На данный момент бизнес-логика не предполагает таких операций, а если требования появятся, то в браузере тоже не составит труда сходить на сервер аяксом в любой момент
Есть у нас и «документные» терминалы, такие как этот habrahabr.ru/post/112726/
Всё же онлайн-модель удобнее и пользователям, и разработчикам.
Если приложение браузерное, оно скорее всего чувствительно к сбоям сети.
Что будет, если в момент выполнения POST-запроса прервётся связь? Браузер выведет страницу с ошибкой?
В нашей архитектуре автомат остаётся в предыдущем состоянии. Оператор повторяет событие (сканирование, нажатие кнопки) и делается повторная попытка отправки.
Всё же онлайн-модель удобнее и пользователям, и разработчикам.
Если приложение браузерное, оно скорее всего чувствительно к сбоям сети.
Что будет, если в момент выполнения POST-запроса прервётся связь? Браузер выведет страницу с ошибкой?
В нашей архитектуре автомат остаётся в предыдущем состоянии. Оператор повторяет событие (сканирование, нажатие кнопки) и делается повторная попытка отправки.
Связь прервется — будет ошибка по таймауту. В принципе, ничего криминального — документ на сервере «отработает» в любом случае.
Да, удобнее и надежнее, соглашусь, но опять-же повторюсь — накладывает более серьезные ограничения на архитектуру сети.
Но и такая модель как я описал — вполне жизнеспособна.
Да, удобнее и надежнее, соглашусь, но опять-же повторюсь — накладывает более серьезные ограничения на архитектуру сети.
Но и такая модель как я описал — вполне жизнеспособна.
А если прервётся до начала POST-запроса, будет потеря данных?
Нет, потери данных не будет в любом случае. Если запрос не ушел или не вернулся, локальные данные остаются неизмененными и могут быть переданы повторно при восстановлении связи. Вручную или автоматически.
Интересно, что пользователь видит в браузере. Например, сервер вернул 503 по каким-то причинам.
Нужно в браузере нажать back и ничего не пропадёт? Документ на сохранение хранится в local storage? Оно есть в IE на WinCE?
Нужно в браузере нажать back и ничего не пропадёт? Документ на сохранение хранится в local storage? Оно есть в IE на WinCE?
Все гораздо проще :)
Кнопок back/forward — нет в принципе. Если делать правильно и через Ajax запросы, то показать можно обычный алерт с фразой «ошибка сохранения, попробуйте еще раз» на любой шухер с сервера. Локального хранилища нет, к сожалению. Приходится работать по-старинке через массивы, циклы. Мельком читал, что есть версии браузеров с поддержкой работы со сканерами на WebKit — там может и есть local storage, не углублялся.
Кнопок back/forward — нет в принципе. Если делать правильно и через Ajax запросы, то показать можно обычный алерт с фразой «ошибка сохранения, попробуйте еще раз» на любой шухер с сервера. Локального хранилища нет, к сожалению. Приходится работать по-старинке через массивы, циклы. Мельком читал, что есть версии браузеров с поддержкой работы со сканерами на WebKit — там может и есть local storage, не углублялся.
У себя используем на моторолловских ТСД их же pocket browser — расширенный ie со встроенными JavaScript библиотеками по работе с аппаратным обеспечением ТСД. По удобству разработки — сносно, но огромный плюс в обновлениях ПО на огромном парке ТСД.
В свое время запускали склад на таких ТСД. В качестве платформы использовали софт компании Клеверенс-Софт… Не сочтите за рекламу, но ребя та сделали очень грамотную и гибкую систему, где разработка бизнес-логики — одно удовольствие. Там по сути не программирование даже, а конфигурирование.
прочитал как «Пишем под ЛСД». Обрадовался
Писал года 4 назад интеграцию с софтом Клеверенс-Софт для нашего приложения.
В принципе у Клеверенс-Софт много чего есть (по организации складского учёта) и достаточно лишь вставить устройство в кредл, нажать на приложение обмен и выгрузить данные в нужном формате. Ну и тоже самое для загрузки.
Тестировал на Motoroll-e и DataLogic-е.
В принципе у Клеверенс-Софт много чего есть (по организации складского учёта) и достаточно лишь вставить устройство в кредл, нажать на приложение обмен и выгрузить данные в нужном формате. Ну и тоже самое для загрузки.
Тестировал на Motoroll-e и DataLogic-е.
Я такую штуку писал под Casio IT-600, а затем ещё на несколько дейвайсов.
Обновлялку делал через .cab файлы.
Для идентификации устройства использовал:
Платформу:
И процессор:
+ функции для старых версий ОС (Возможно сейчас уже и не пригодятся)
Итого:
А работало это всё через «завод» с использованием ScanAPI или OBR. На выбор.
Проект писался в 2009 году. Возможно с тех времён что-то и поменялось…
Но если кому интересно, могу выложить некоторые куски. Может кому-то пригодятся.
Обновлялку делал через .cab файлы.
Для идентификации устройства использовал:
Платформу:
public const UInt32 SPI_GETPLATFORMTYPE = 257;
[DllImport("coredll")]
public extern static Boolean SystemParametersInfo(
UInt32 uiAction,
UInt32 uiParam,
StringBuilder pvParam,
UInt32 fWinIni);
public static String GetPlatformType()
{
StringBuilder sb = new StringBuilder(255);
if(Environment.OSVersion.Platform == PlatformID.Win32NT)
return "WIN32";//NativeMethods.SystemParametersInfoWin32(NativeMethods.SPI_GETPLATFORMTYPE, (UInt32)sb.Capacity, sb, 0);
else
NativeMethods.SystemParametersInfo(NativeMethods.SPI_GETPLATFORMTYPE, (UInt32)sb.Capacity, sb, 0);
String platType = sb.ToString();
switch(platType)
{
case "PocketPC":
return "PPC";
case "Windows CE":
return "WCE";
case "Phoenix"://Casio IT-600
return "Phoenix";
default:
return platType;
}
}
И процессор:
[DllImport("Coredll")]
public extern static Boolean QueryInstructionSet(
UInt32 dwInstructionSet,
out CpuInstructionSet CurrentInstructionSet
);
public enum CpuInstructionSet
{
X86 = Constant.Processor.PROCESSOR_X86_32BIT_INSTRUCTION,
SH3 = Constant.Processor.PROCESSOR_HITACHI_SH3_INSTRUCTION,
SH4 = Constant.Processor.PROCESSOR_HITACHI_SH4_INSTRUCTION,
MIPSV4 = Constant.Processor.PROCESSOR_MIPS_MIPSIV_INSTRUCTION,
MIPSV4_FP = Constant.Processor.PROCESSOR_MIPS_MIPSIVFP_INSTRUCTION,
MIPSVII = Constant.Processor.PROCESSOR_MIPS_MIPSII_INSTRUCTION,
MIPSVII_FP = Constant.Processor.PROCESSOR_MIPS_MIPSIIFP_INSTRUCTION,
MIPS16 = Constant.Processor.PROCESSOR_MIPS_MIPS16_INSTRUCTION,
ARMV4 = Constant.Processor.PROCESSOR_ARM_V4_INSTRUCTION,
ARMV4T = Constant.Processor.PROCESSOR_ARM_V4T_INSTRUCTION,
ARMV4I =Constant.Processor.PROCESSOR_ARM_V4I_INSTRUCTION,
ARMV4FP = Constant.Processor.PROCESSOR_ARM_V4FP_INSTRUCTION,
ARMV4IFP = Constant.Processor.PROCESSOR_ARM_V4IFP_INSTRUCTION,
ARMV4TFP = Constant.Processor.PROCESSOR_ARM_V4TFP_INSTRUCTION,
}
+ функции для старых версий ОС (Возможно сейчас уже и не пригодятся)
internal struct SYSTEM_INFO
{
public UInt16 wProcessorArchitecture;
public UInt16 wReserved;
public UInt32 dwPageSize;
public Int32 lpMinimumApplicationAddress;
public Int32 lpMaximumApplicationAddress;
public UInt32 dwActiveProcessorMask;
public UInt32 dwNumberOfProcessors;
public UInt32 dwProcessorType;
public UInt32 dwAllocationGranularity;
public UInt16 wProcessorLevel;
public UInt16 wProcessorRevision;
}
[DllImport("Coredll")]
public extern static void GetSystemInfo(ref SYSTEM_INFO SystemInfo);
[DllImport("Kernel32.dll", EntryPoint = "GetSystemInfo")]
public extern static void GetSystemInfoWin32(ref SYSTEM_INFO SystemInfo);
Итого:
public static String GetInstructionSet()
{
CpuInstructionSet iset = CpuInstructionSet.X86;
try
{
if(Environment.OSVersion.Platform == PlatformID.Win32NT)
return iset.ToString();
else
NativeMethods.QueryInstructionSet(0, out iset);
}
catch(MissingMethodException)
{
SYSTEM_INFO si = new SYSTEM_INFO();
if(Environment.OSVersion.Platform == PlatformID.Win32NT)
NativeMethods.GetSystemInfoWin32(ref si);
else
NativeMethods.GetSystemInfo(ref si);
switch(si.wProcessorArchitecture)
{
case Constant.Processor.Architecture.PROCESSOR_ARCHITECTURE_ARM:
return CpuInstructionSet.ARMV4.ToString();
case Constant.Processor.Architecture.PROCESSOR_ARCHITECTURE_SHX:
return CpuInstructionSet.SH3.ToString();
case Constant.Processor.Architecture.PROCESSOR_ARCHITECTURE_INTEL:
return CpuInstructionSet.X86.ToString();
case Constant.Processor.Architecture.PROCESSOR_ARCHITECTURE_MIPS:
return CpuInstructionSet.MIPSV4.ToString();
default:
return "Unkown_"+si.wProcessorArchitecture.ToString();
}
}
return iset.ToString();
}
А работало это всё через «завод» с использованием ScanAPI или OBR. На выбор.
Проект писался в 2009 году. Возможно с тех времён что-то и поменялось…
Но если кому интересно, могу выложить некоторые куски. Может кому-то пригодятся.
У меня сейчас аццкая поделка под название Mobile logistics. Как раз потому что оборудование на wince. Подождали бы чуть-чуть, купили бы на андроиде — писал бы на относительно нормальной 1ске.
Sign up to leave a comment.
Пишем под ТСД. Подключение сканера штрихкода, как компонент формы