- Доставка на следующий день
- Как подключить и настроить диагностический автомобильный сканер кодов obd ii can?
- Какой функционал входит в «таксомёт» в настоящее время?
- Модифицированный таксометр
- Рецензия на сериал «области тьмы. сезон 1»
- Сканер s7000hl4 v.5.79-can , цена 3300руб. купить в интернет магазине в краснодаре. доставка по всей россии!
- Софт панели приборов на python и kivy (ui framework)
Доставка на следующий день
При оформлении заказа до 14 часов текущего дня доставка осуществляется на следующий рабочий день.Стоимость доставки по Санкт-Петербургу составляет всего 270 руб. Доставка осуществляется с 10 до 18 ч.
Для отправки заказов в Москву в пределах МКАД действуют два тарифа: стандарт и эконом.- Стандарт 410 рублей. Экспресс-доставка “до дверей” на следующий рабочий день, если заказ сделан до 14 часов текущего дня. Курьер доставит Вам посылку по указанному адресу с 10 до 18 часов, за 1 час до доставки свяжется с Вами по телефону.
– Эконом 310 рублей. Доставка “до дверей” в течение двух рабочих дней (по усмотрению курьерской компании), если заказ сделан до 14 часов текущего дня. Курьер доставит Вам посылку по указанному адресу с 10 до 18 часов, за 1 час до доставки свяжется с Вами по телефону.
Оплата за товар доставка производится курьеру при передаче Вам товара, оплата только наличными.
*Стоимость доставки за пределы МКАД смотрите ниже.
Для ускорения сроков доставки заказов мы отправляем все заказы только Первым классом. Сроки доставки по РФ – от 5 до 12 дней.При 100% предоплате – стоимость доставки 350 руб. Отправка проиходит в течение 2-х дней после оформления заказа.** Как правило, отправляем в день заказа или на следующий день, кроме воскресенья и праздничных дней.
При наложенном платеже (оплата на почте при получении) помимо почтовых расходов получатель оплачивает комиссию 4% от стоимости посылки за перевод денежных средств отправителю.Тарифы отправления Первого Класса почты России.
Отправка наложенным платежом осуществляется при заказе от 600 рублей, заказы до 600 рублей только по предоплате.
При заказе от 600 до 2000 рублей – стоимость доставки 450 руб комиссия 100-160 руб.При заказе от 2001 до 3000 рублей – стоимость доставки 500 руб комиссия 160-200 руб.При заказе от 3001 до 4000 рублей – стоимость доставки 550 руб комиссия 200-240 руб.
В форме заказа укажите индекс, точный адрес, ФИО получателя.
Доставка курьерской службой EMS возможна наложенным платежом и по предоплате. Доставка за 3-7 дней.Обратите внимание, что доставка производится в рабочие с 9:00 до 18:00, приезд курьера к фиксированному времени невозможен. Воспользуйтесь расчётом – КАЛЬКУЛЯТОР СТОИМОСТИ
Отправка возможна как по предоплате, так и наложенным платежом. Забор груза осуществляется по будням.Стоимость пересылки оплачивается клиентом при получении (от 400 руб), возможна доставка до адреса.Воспользуйтесь расчётом – КАЛЬКУЛЯТОР СТОИМОСТИ.
Доставка курьерской службой PONY EXPRESS возможна только при 100% предоплате. Доставка за 2-5 дней.Воспользуйтесь расчётом – КАЛЬКУЛЯТОР СТОИМОСТИ
Отправка только при 100% предоплате. Доставка до терминала транспортной компании осуществляется каждую пятницу.Если требуется срочная доставка, то возможно доставка до терминала на следующий день после оплаты за 300 руб.
Стоимость пересылки оплачивается клиентом при получении (от 400 р.) на терминале ПЭК в городе назначения, также возможна доставка до адреса за дополнительную плату.Воспользуйтесь расчётом – КАЛЬКУЛЯТОР СТОИМОСТИ. Общая сумма с доставкой до адреса от 750 рублей. Доставка 2-10 дней по России. Филиальная сеть ПЭК обширна, города доставки – СПИСОК.
Отправка только при 100% предоплате. Доставка до терминала транспортной компании осуществляется каждую пятницу, стоимость доставки до терминала – 100 руб., остальную сумму за перевозку оплачиваете при получении на терминале.
Если требуется срочная доставка, то возможно доставка до терминала на следующий день после оплаты за 300 руб.Стоимость пересылки оплачивается клиентом при получении (от 470 р.) на терминале Деловых Линий в городе назначения, также возможна доставка до адреса за дополнительную плату.
Курьер по России до двери.
ПОЛНЫЙ СПИСОК ГОРОДОВ В РАЗДЕЛЕ ОПЛАТА И ДОСТАВКА.
Как подключить и настроить диагностический автомобильный сканер кодов obd ii can?
Как подключить и настроить диагностический автомобильный сканер кодов OBD II CAN?
КРАТКОЕ СОДЕРЖАНИЕ:
- Подключите устройство к телефону по Bluetooth
- Подключите устройство в настройках программы Torque
После покупки автомобильного диагностического сканера кодов OBD 2 нам очень часто задают вопрос – как его использовать? Действительно, разобраться с подключением бывает непросто, особенно, когда первый раз держишь устройство в руках. Именно поэтому мы написали данную статью – надеемся, она поможет Вам приступить к работе с устройством сразу после покупки и не терять драгоценное время.
Для начала давайте рассмотрим само устройство. Оно представляет собой небольшую коробочку, которая является, фактически, переходником для подключения Вашего смартфона к автомобилю через Bluetooth. Всей расшифровкой и обработкой информации занимается Ваш телефон – при помощи специальной установленной программы. Именно наличие практически у каждого человека небольшого смартфона сделало возможным производство бытовых автомобильных сканеров OBD II. Раньше для расшифровки использовались мощные компьютеры, которые устанавливались только в автосервисах. А теперь проверить состояние всех систем Вашего железного коня можно так же легко, как сделать покупку в обычном магазине! А самое главное – автомобильный сканер является «мультимарочным», то есть, подходит для абсолютно любого автомобиля!
Но вернемся к нашему устройству:
Рис. 1. Внешний вид автомобильного диагностического сканера OBD 2
В некоторых моделях сканеров в комплекте с устройством идет диск с программным обеспечением. Но на самом деле, для работы он совершенно не обязателен. Все, что нам нужно – это само устройство и смартфон.
Первое, что нам нужно – это найти диагностический разъем в автомобиле. Многие люди сразу лезут под капот, но в большинстве случаев разъем находится внутри салона, где-то под рулевой колонкой. Скажем честно – чтобы его обнаружить, придётся постараться. Советуем использовать фонарик. Зато после того, как он будет найден, Вы сможете устанавливать сканер не глядя.
Следующим шагом идет установка самого сканера. Желательно производить установку при заглушенном автомобиле. Разъем устроен таким образом, что неправильно вставить устройство невозможно.
После установки в разъем на устройстве загорится индикатор.
Теперь нам понадобится сама программа. Мы (сотрудники интернет-магазина «Азиада») пользуемся смартфонами на Андроиде, поэтому статью пишем исходя из собственного опыта. На смартфонах с другими операционными системами процесс будет очень похож, мы уверены, что Вы без труда разберётесь.
Итак, открываем Google Play Market. Существует большое количество программ для диагностики, они отличаются возможностями, интерфейсом и т.д.. Лично мы используем программу Torque – управление в ней интуитивно понятно и не требует каких-либо особых знаний. Впоследствии Вы всегда сможете установить другой софт.
Рис. 2. Приложения в Play Market при поисковом запросе «Torque»
Вбив в поисковую строку «Torque», мы увидим, что таких программ две – платная версия и бесплатная (см. рис. 2). Для начала есть смысл не тратить деньги и поставить бесплатную версию. В 99% случаев ее возможностей достаточно.
Устанавливаем…
И получаем вот такой ярлык на рабочем столе:
Рис. 3. Ярлык программы «Torque» на рабочем столе
Теперь нам нужно соединить смартфон и автомобильный диагностический сканер кодов через Bluetooth. Соединение происходит в два этапа – первым этапом мы должны объяснить Андроиду, что у нас есть новое Bluetooth – устройство и нам нужно его подключить к телефону. Вторым этапом мы должны объяснить программе Torque, что подключенное по беспроводному каналу устройство и есть наш сканер.
Для этого открываем в вашем телефоне «настройки», выбираем закладку «Bluetooth», затем в списке ищем сканер. Если его там нет – вытащите и установите его в разъем еще раз, возможно, он просто впал в «спящий режим».
Рис. 4. Подключение автомобильного диагностического сканера через Bluetooth
Иногда прибор определяется весьма странно, например, как на рисунке – 00:11:10:24:03:49. Но после того, как Вы его подключите, он обретет свое «настоящее» имя и станет называться Aut-Tech.
Итак, щелкаем на устройство в списке. Выскочит окошко, в котором нужно будет ввести пароль – 1234. Возможно, у других устройств пароль будет другим, но это всегда простейшее сочетание символов – 1111, 0000, 1234, 123456 и так далее. После ввода пароля нажмите клавишу «ОК».
Рис. 5. Запрос пароля для подключения
Устройство будет подключено. Обратите внимание на забавный факт – на многих смартфонах значок беспроводного соединения не меняет цвет!
Тем не менее, в списке появится надпись – «авторизовано».
Рис. 6. Устройство Aut-Tech авторизовано
Теперь запускаем саму программу. Затем на экране щёлкаем на кнопку с шестеренкой – это «настройки». В зависимости от типа Вашего устройства и диагонали экрана внешний вид может отличаться от наших картинок. В некоторых случаях настройки вызываются нажатием на отдельную кнопку на корпусе смартфона. Это зависит только от модели аппарата, который Вы используете.
После нажатия появится меню, в котором выбираем «настройки»:
Рис. 7. Кнопка «Меню» в программе «Torque»
В настройках среди прочего нам нужно проверить раздел «Connection» – должно быть установлено «Bluetooth» (бывают адаптеры с подключением по Wi-Fi, настраиваются практически так же).
И самое главное – нажмите на раздел «Device». Выскочит список всех устройств, которые Вы подключали по Bluetooth – Ваши гарнитуры, беспроводные колонки и прочее. В списке выберите Aut-Tech – это и есть наш диагностический сканер.
Рис. 8. Интересующие нас пункты меню
Рис. 9. Выбор устройства Bluetooth
Примечание: В нашем случае мы ничего не подключали к данному планшету ранее, поэтому в списке и присутствует только «Aut-Tech». У Вас ситуация может быть немного иная.
ПОЗДРАВЛЯЕМ! УСТРОЙСТВО ПОДКЛЮЧЕНО И РАБОТАЕТ!
Как это проверить? Самый простой вариант – считать показания какого-либо датчика. Идеально для этих целей подходит датчик напряжения на аккумуляторе. Для этого в основном меню программы на пустом поле задержите палец на несколько секунд. Появится меню, выберите «Add Display» -> «Display» -> «Voltage». Выберите желаемый размер дисплея, и он будет помещен на рабочий стол программы. Заведите машину – и индикатор покажет напряжение – 14 вольт когда машина заведена, или 12 вольт если мотор заглушен.
Рис. 10. Напряжение на аккумуляторе
Какой функционал входит в «таксомёт» в настоящее время?
- Web-интерфейс для руководителя и операторов диспетчерской
- Программа для Android для водителей
- SIP телефония
- Информирование клиентов такси с помощью голосового автоинформатора через Вашу телефонную линию
- Очередь входящих звонков (клиенту сообщается номер очереди при ожидании связи с оператором)
- IVR: клиент может связаться с водителем нажав 1, отказаться от заказа нажав 2 без соединения с оператором
- SMS информирование клиентов такси (дополнительная платная услуга)
- Учет расчетов с водителями и операторами деспетчерской согласно установленным тарифам
- Сдельные тарифы для водителей, а так же безлимитные тарифы
- Возможность работы по рации
- Мониторинг транспорта, запись треков
- Эффективная система раздачи заказов водителям, встречные заказы
- GPS таксометр, а так же пробег с бортового компьютера автомобиля (через OBD-2 разъем)
- Расчет предварительной стоимости поездки по кратчайшему пути
- Расчет предварительной стоимости по сетке тарифов (трансферы)
- Возможность массовых рассылок сообщений водителям (бесплатно, даже если вобитель выключил программу.)
- Отчеты для руководителя
- Отчеты для операторов диспетчерской
- Разделение учета и прав по подразделениям такси (одна диспетчерская на несколько служб такси)
- Учет накопительных скидок клиентов
- Пополнение баланса водителя через QIWI, c банковской карты (комиссия 2%)
- Черный список клиентов
- Безналичные расчеты
- Фотоосмотры автомобилей, запросы на выполнение снимков любых документов (например, водителького удостоверения, страховки, техосмотра и прочее) Подробнее…
- Ваш личный сайт с формой заказа, с расчетом окончательной стоимости (а так же мобильная версия сайта). Пример сайта одного из наших клиентов(рабочий сайт, просьба ложные заказы не делать). Чтобы увидеть мобильную версию зайдите на сайт со смартфона или планшета.
- Приложение на Android для клиентов (с Вашим названием) с расчетом стоимости, историей заказа, картами, оплатой банковскими картами и др.
- Приложение на iOS (iPhone) для клиентов (с Вашим названием) с расчетом стоимости, историей заказа, картами, оплатой банковскими картами и др.
- Робот-диспетчер.Подробнее…
- Он-лайн кассы (ФЗ-54).Новое Выдаёт QR-код чека в мобильном приложении. Подробнее…
- Обменник заказами такси. (Биржа такси) Новое Обмен заказами со службами работающими на ПО “Таксомёт”, а так же на другом программном обеспечении, имеющим интеграцию с “Таксомёт”. Подробнее…
- Многое другое!
Возникли вопросы по функционалу программы? Спросите у нас.
Модифицированный таксометр
Рецензия на сериал «области тьмы. сезон 1»
Limitless
драма, триллер, фантастика
Режиссеры:Дуглас Аарниокоски
,
Питер Уэрнер
,
Марк Уэбб
,
Стивен Э. Эделсон
,
Джошуа Батлер
В ролях:Джейк Макдорман
,
Дженнифер Карпентер
,
Хилл Харпер
,
Мэри Элизабет Мастрантонио
,
Том Деньян
У наркоторговцев Нью-Йорка появляется новый продукт – загадочный синтетический препарат NZT. Он на двенадцать часов превращает человека в интеллектуального гиганта с идеальной памятью, невероятными способностями к обучению, запредельной интуицией и фантастической реакцией. Однако побочные эффекты NZT столь губительны, что принимать препарат могут лишь самоубийцы. Внезапно ФБР обнаруживает молодого разгильдяя-музыканта Брайана Финча (Джейк МакДорман) с иммунитетом от побочных эффектов NZT. Не желая упустить такую возможность, бюро делает Финча консультантом по расследованию особо опасных преступлений. В ФБР не знают, что Финч – «засланный казачок» видного политика Эдварда Морра (Брэдли Купер). Морра уже давно знает о существовании NZT, и его химики разработали сыворотку, которая на время защищает от побочных эффектов. Финч получает эту сыворотку в обмен на обязательство быть глазами и ушами Морра в ФБР и не позволять своим новым сослуживцам «копать» под политика, который претендует на пост президента США.
В прошлом телесезоне Джейк МакДорман был главным героем романтического телеситкома «Манхэттенская история любви». Это шоу продержалось в эфире всего 11 серий
Есть в Америке такая традиция – создавать сериалы на основе известных и не очень известных фильмов. Вспомним хотя бы чрезвычайно успешную «Баффи – истребительницу вампиров» или, наоборот, продержавшегося всего один сезон «Блейда». «Области тьмы» ведущего эфирного канала CBS – очередной представитель этого направления, вдохновленный одноименной картиной 2021 года. В отличие от большинства подобных постановок, герой исходного фильма Брэдли Купер фигурирует в новом шоу, но он появляется лишь в нескольких сериях и почти всегда только в небольших фрагментах. Так что поклонникам Купера не стоит на многое рассчитывать. Это шоу не звезды «Мальчишника в Вегасе», а Джейка МакДормана из сериала «Университет».
Дженнифер Карпентер стала матерью во время съемок «Областей тьмы». Она была на последнем месяце беременности, когда снималась в пилотной серии
К счастью, Брайан Финч – куда более занятный персонаж, чем Эдвард Морра. Поначалу он кажется эталонным американским «лузером», который только и умеет, что бренчать на гитаре, курить «травку» и цитировать культовые комедии. Но по мере развития сюжета Финч обрастает все новыми забавными причудами (так, он проводит одну из серий в попытках доказать, что у него должен быть собственный офис с табличкой «штаб-квартира») и полученными благодаря NZT неожиданными и «ожиданными» талантами. В результате уже к концу первого сезона Финч оказывается чем-то средним между Джеймсом Бондом, Лисбет Саландер, суперлингвистом… И все тем же разгильдяем с «травкой» и любимыми фильмами.
Мы уже видели подобное сочетание в шпионском сериале «Чак», но герой Закари Ливая был куда менее обаятельным и изобретательным. Кроме того, Чак был стереотипным «ботаном», а Финч получает благодаря NZT лишь «ботанические» способности. У него нет «ботанических» недостатков вроде трусости, нелюдимости, обиженности на мир, саркастичного чувства юмора. Это улыбчивый и хулиганистый рубаха-парень, который обожает свою семью, хранит верность друзьям и следует строгим моральным принципам – конечно, когда его не шантажируют люди Морра. Главное же его достоинство – умение постоянно придумывать новые способы раскрывать преступления, иллюстрировать свои «завиральные» идеи и влиять на людей. Так что следить за его похождениями – масса удовольствия для поклонников детективных сериалов, уставших от жанровой монотонности и от модных сейчас «колючих» и аутичных сыщиков.
Другое дело, что такой обаятельный и полукомичный персонаж не очень вписывается в те серии, где «Области тьмы» берут за рога свой сквозной сюжет об интригах Морра и нагнетают мрачноватый драматизм. Поэтому худшие эпизоды сезона сосредоточены в его начале и в конце. Наоборот, основное, более расслабленное «тело» сезона позволяет в полной мере раскрыться всем ребячливым причудам и талантам Финча – как под NZT, так и без него. Наивысшей же точки шоу достигает в иронических эпизодах вроде седьмой и восьмой серий, где Финч соответственно представляет происходящее с ним в терминах комедии «Феррис Бьюллер берет выходной» и разыскивает современных южноазиатских пиратов.
Команда поддержки Брайана не столь примечательна, как он сам, но в ней есть запоминающиеся лица вроде Дженнифер Карпентер из «Правосудия Декстера», Мэри Элизабет Мастрантонио из «Робин Гуда: Принца воров» и чернокожего британца Колина Сэлмона из трех фильмов «бондианы».
В целом «Области тьмы» – достойный детективный трагикомичный сериал с ярким главным героем. В большинстве эпизодов шоу удается поддерживать баланс между криминальной интригой, юмором и душевностью, и если у вас нет аллергии на ребячливое раздолбайство, к которому порой склонен Брайан, то «Областям» стоит дать шанс. Другое дело, что это отнюдь не «обязательное к просмотру» зрелище, а просто хорошая альтернатива депрессивным теледетективам вроде «Мыслить как преступник» или шаблонной жанровой жвачке вроде канадского «Мотива».
Сканер s7000hl4 v.5.79-can , цена 3300руб. купить в интернет магазине в краснодаре. доставка по всей россии!
Автомобильный диагностический тестер-сканер S7000HL4 предназначен для использования в качестве средства диагностики автомобилей с распределенным впрыском производства АО АВТОВАЗ (РЕНО-НИССАН), GM-АВТОВАЗ, а также ГАЗ и др.
Тестер выпускается в 2-х вариантах: со встроенным USB портом и без него.
Автомобильный диагностический тестер-сканер S7000HL4 поддерживает работу со следующими электронными системами, установленными на автомобиле:
-ЭЛЕКТРОННАЯ СИСТЕМА УПРАВЛЕНИЯ ДВИГАТЕЛЕМ (ЭСУД)
-АВТОМАТИЧЕСКАЯ КОРОБКА ПЕРЕДАЧ (АКП)
-ИММОБИЛИЗАТОР (АПС)
-ЭЛЕКТРОПАКЕТ (ЭП) и ЦЕНТРАЛЬНЫЙ БЛОК КУЗОВНОЙ ЭЛЕКТРОНИКИ (ЦБКЭ)
-МОДУЛЬ ДВЕРИ ВОДИТЕЛЯ (МДВ)
-СИСТЕМА УПРАВЛЕНИЯ НАДУВНОЙ ПОДУШКОЙ БЕЗОПАСНОСТИ (СНПБ)
-СИСТЕМА ОТОПЛЕНИЯ/ КОНДИЦИОНЕР (САУО/ САУКУ)
-ЭЛЕКТРОМЕХАНИЧЕСКИЙ УСИЛИТЕЛЬ РУЛЯ (ЭМУР)
-АНТИБЛОКИРОВОЧНАЯ СИСТЕМА ТОРМОЗОВ (АБС)
-БЛОК УПРАВЛЕНИЯ СТЕКЛООЧИСТИТЕЛЕМ и ОСВЕЩЕНИЕМ (БУСО)
-РЕГИСТРАТОР ПУТЕВЫХ ПАРАМЕТРОВ (‛ЧЕРНЫЙ‛ ЯЩИК )
Автомобильный диагностический тестер рассчитан на работу с контроллерами ЭСУД:
-M1.5.4, M1.5.4N, М7.9.7, MP7.0, MP7.0H, ME17.9.7 ‛BOSCH‛
-ЯНВАРЬ-5.1, ЯНВАРЬ-5.1.1, ЯНВАРЬ-5.1.2, ЯНВАРЬ-7.2
-VS5.1 ИТЕЛМА
-M73, M74, M74-CAN, M86 (Веста)
-М10.3, M11, M11-ет МИКАС (Газель)
-EMS-3132 РЕНО
Следует учитывать, что работа с системами ЭП, МДВ, ПБ, САУО/САУКУ, ЭМУР, БУСО, АБС и АКП возможна только при их наличии в комплектации автомобиля! Связь тестера с электронными системами автомобиля осуществляется либо по однопроводной двунаправленной К-линии связи, выполненной в стандарте ISO 9141-2, либо по CAN –интерфейсу в стандарте ISO 15765, либо по КL для диагностики автомобилей платформы В0 (LARGUS, LOGAN , SANDERO и др.). Распознавание типа контроллера ЭСУД, типа интерфейса и протокола – автоматическое.
Тестер пригоден для диагностики ряда иномарок и даже входит в комплект поставки вертолета АК13.
Подготовка к перепрограммированию и установка драйвера
Подключить тестер к компьютеру USB кабелем, входящим в комплект. Вставить в CD привод прилагаемый компакт-диск. После того, как операционная система обнаружит новое устройство USB serial port, установить драйвер устройства. Для этого указать путь на компакт-диске /2 Драйверы USB/ и далее выбрать папку с версией драйвера, соответствующей операционной системе, установленной на Вашем компьютере. После этого может потребоваться перезагрузка компьютера.
Описание программы-загрузчика
Шаг 1:
Запустить программу-загрузчик straus.exe
Шаг 2:
Выбрать файл для загрузки
Шаг 3:
Выбрать доступный виртуальный COM порт
Шаг 4:
Выбрать в меню “Начать загрузку”
Шаг 5:
После появления сообщения “ВКЛЮЧИ ПИТАНИЕ” выбрать пункт меню тестера >>F-ПЕРЕХ.В ПРОГРАММИ.<< и войти в него, удерживая нажатой кнопку “->” в течение 2…3Сек. Должен начаться процесс загрузки нового ПО. Примечание: Без подключения разъема тестера либо к источнику питания, либо к диагностической колодке индикация на дисплее тестера будет слабозаметной и без подсветки.
Шаг 6:
По окончании загрузки выйти из программы straus.exe
Во время программирования информация на дисплей диагностического тестера не выводится. По окончании процесса программирования появляется главное меню.
Примечание: Если не подключать диагностический разъем тестера и программировать без подачи напряжения питания 12В на тестер, то сообщения на дисплее будут слаборазличимы и не будет подсветки. Кнопки тестера придется нажимать вслепую (шаг 5: нажатие кнопки “-” и затем кнопки “->” в течение 2..3 Сек), но на процессе программирования это никак не отразится и программирование так-же будет сопровождаться светодиодной индикацией.
Тестер имеет светодиодную индикацию наличия передаваемых (TXD) и принимаемых (RXD) по USB данных. Светодиоды находятся справа от кнопки Р2.
Скачать руководство по эксплуатации тестера S7000HL4 v.5.79-CAN/USB
Софт панели приборов на python и kivy (ui framework)
Параллельно со сборкой самой панели приборов я вел разработку приложения для отображения информации с датчиков. В самом начале я не планировал какой либо дизайн.
Первая версия панели приборов
По мере разработки решил визуализировать данные более наглядно. Хотел гоночный дизайн, а получилось, что-то в стиле 80-х.
Вторая версия панели приборов
Продолжив поиски более современного дизайна я обратил внимание какие цифровые приборки делают автопроизводители и постарался сделать что-то похожее.
Третья версия панели приборов
Ранее, я никогда не разрабатывал графические приложения под Linux поэтому не знал с чего начать. Вариант на вебе простой в разработке, но слишком много лишних компонентов: иксы, браузер, nodejs, хотелось быстрой загрузки. Попробовав Qt PySide2 я понял, что это займет у меня много времени, т.к. мало опыта.
Kivy позволяет запускать приложение без Иксов, прямо из консоли, в качестве рендера используется OpenGL. Благодаря этому полная загрузка системы может происходить за 10 секунд.
import can
import os
import sys
from threading import Thread
import time
os.environ['KIVY_GL_BACKEND'] = 'gl'
os.environ['KIVY_WINDOW'] = 'egl_rpi'
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.properties import BoundedNumericProperty
from kivy.properties import StringProperty
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.scatter import Scatter
from kivy.animation import Animation
messageCommands = {
'GET_DOORS_COMMAND': 0x220D,
'GET_OIL_TEMPERATURE' : 0x202F,
'GET_OUTDOOR_TEMPERATURE' : 0x220C,
'GET_INDOOR_TEMPERATURE' : 0x2613,
'GET_COOLANT_TEMPERATURE' : 0xF405,
'GET_SPEED' : 0xF40D,
'GET_RPM' : 0xF40C,
'GET_KM_LEFT': 0x2294,
'GET_FUEL_LEFT': 0x2206,
'GET_TIME': 0x2216
}
bus = can.interface.Bus(channel='can0', bustype='socketcan')
# -*- coding: utf-8 -*-
import can
import os
import sys
from threading import Thread
import time
os.environ['KIVY_GL_BACKEND'] = 'gl'
os.environ['KIVY_WINDOW'] = 'egl_rpi'
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.properties import BoundedNumericProperty
from kivy.properties import StringProperty
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.scatter import Scatter
from kivy.animation import Animation
messageCommands = {
'GET_DOORS_COMMAND': 0x220D,
'GET_OIL_TEMPERATURE' : 0x202F,
'GET_OUTDOOR_TEMPERATURE' : 0x220C,
'GET_INDOOR_TEMPERATURE' : 0x2613,
'GET_COOLANT_TEMPERATURE' : 0xF405,
'GET_SPEED' : 0xF40D,
'GET_RPM' : 0xF40C,
'GET_KM_LEFT': 0x2294,
'GET_FUEL_LEFT': 0x2206,
'GET_TIME': 0x2216
}
bus = can.interface.Bus(channel='can0', bustype='socketcan')
class PropertyState:
def __init__(self, last, current):
self.last = last
self.current = current
def lastIsNotNow(self):
return self.last is not self.current
class CanListener(can.Listener):
def __init__(self, dashboard):
self.dashboard = dashboard
self.speedStates = PropertyState(None,None)
self.rpmStates = PropertyState(None,None)
self.kmLeftStates = PropertyState(None,None)
self.coolantTemperatureStates = PropertyState(None,None)
self.oilTempratureStates = PropertyState(None,None)
self.timeStates = PropertyState(None,None)
self.outDoorTemperatureStates = PropertyState(None,None)
self.doorsStates = PropertyState(None,None)
self.carMinimized = True
def on_message_received(self, message):
messageCommand = message.data[3] | message.data[2] << 8
if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_SPEED']:
self.speedStates.current = message.data[4]
if self.speedStates.lastIsNotNow():
self.dashboard.speedometer.text = str(self.speedStates.current)
self.speedStates.last = self.speedStates.current
if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_RPM']:
self.rpmStates.current = message.data[5] | message.data[4] << 8
if self.rpmStates.lastIsNotNow():
self.dashboard.rpm.value = self.rpmStates.current/4
self.rpmStates.last = self.rpmStates.current
if message.arbitration_id == 0x35B:
self.rpmStates.current = message.data[2] | message.data[1] << 8
if self.rpmStates.lastIsNotNow():
self.dashboard.rpm.value = self.rpmStates.current/4
self.rpmStates.last = self.rpmStates.current
if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_KM_LEFT']:
self.kmLeftStates.current = message.data[5] | message.data[4] << 8
if self.kmLeftStates.lastIsNotNow():
self.dashboard.kmLeftLabel.text = str(self.kmLeftStates.current)
self.kmLeftStates.last = self.kmLeftStates.current
if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_COOLANT_TEMPERATURE']:
self.coolantTemperatureStates.current = message.data[4]
if self.coolantTemperatureStates.lastIsNotNow():
self.dashboard.coolantLabel.text = str(self.coolantTemperatureStates.current-81)
self.coolantTemperatureStates.last = self.coolantTemperatureStates.current
if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_OIL_TEMPERATURE']:
self.oilTempratureStates.current = message.data[4]
if self.oilTempratureStates.lastIsNotNow():
self.dashboard.oilLabel.text = str(self.oilTempratureStates.current-58)
self.oilTempratureStates.last = self.oilTempratureStates.current
if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_TIME']:
self.timeStates.current = message.data[5] | message.data[4] << 8
if self.timeStates.lastIsNotNow():
self.dashboard.clock.text = str(message.data[4]) ":" str(message.data[5])
self.timeStates.last = self.timeStates.current
if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_OUTDOOR_TEMPERATURE']:
self.outDoorTemperatureStates.current = float(message.data[4])
if self.outDoorTemperatureStates.lastIsNotNow():
self.dashboard.outDoorTemperatureLabel.text = str((self.outDoorTemperatureStates.current - 100)/2)
self.outDoorTemperatureStates.last = self.outDoorTemperatureStates.current
if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_DOORS_COMMAND']:
self.doorsStates.current = message.data[4]
if self.doorsStates.lastIsNotNow():
self.doorsStates.last = self.doorsStates.current
self.dashboard.car.doorsStates=message.data[4]
# all doors closed -> minimize car
if self.doorsStates.current == 0x55:
self.dashboard.minimizeCar()
self.carMinimized = True
else:
if self.carMinimized:
self.dashboard.maximizeCar()
self.carMinimized = False
class Dashboard(FloatLayout):
def __init__(self,**kwargs):
super(Dashboard,self).__init__(**kwargs)
# Background
self.backgroundImage = Image(source='bg.png')
self.add_widget(self.backgroundImage)
# RPM
self.rpm = Gauge(file_gauge = "gauge512.png", unit = 0.023, value=0, size_gauge=512, pos=(0,0))
self.add_widget(self.rpm)
self.rpm.value = -200
# Speedometer
self.speedometer = Label(text='0', font_size=80, font_name='hemi_head_bd_it.ttf', pos=(0,-15))
self.add_widget(self.speedometer)
# KM LEFT
self.kmLeftLabel = Label(text='000', font_name='Avenir.ttc', halign="right", text_size=self.size, font_size=25, pos=(278,233))
self.add_widget(self.kmLeftLabel)
# COOLANT TEMPEARATURE
self.coolantLabel = Label(text='00', font_name='hemi_head_bd_it.ttf', halign="right", text_size=self.size, font_size=27, pos=(295,-168))
self.add_widget(self.coolantLabel)
# OIL TEMPERATURE
self.oilLabel = Label(text='00', font_name='hemi_head_bd_it.ttf', halign="right", text_size=self.size, font_size=27, pos=(-385,-168))
self.add_widget(self.oilLabel)
# CLOCK
self.clock = Label(text='00:00', font_name='Avenir.ttc', font_size=27, pos=(-116,-202))
self.add_widget(self.clock)
# OUTDOOR TEMPERATURE
self.outDoorTemperatureLabel = Label(text='00.0', font_name='Avenir.ttc', halign="right", text_size=self.size, font_size=27, pos=(76,-169))
self.add_widget(self.outDoorTemperatureLabel)
# CAR DOORS
self.car = Car(pos=(257,84))
self.add_widget(self.car)
def minimizeCar(self, *args):
print("min")
anim = Animation(scale=0.5, opacity = 0, x = 400, y = 240, t='linear', duration=0.5)
anim.start(self.car)
animRpm = Animation(scale=1, opacity = 1, x = 80, y = -5, t='linear', duration=0.5)
animRpm.start(self.rpm)
def maximizeCar(self, *args):
print("max")
anim = Animation(scale=1, opacity = 1, x=257, y=84, t='linear', duration=0.5)
anim.start(self.car)
animRpm = Animation(scale=0.5, opacity = 0, x = 80, y = -5, t='linear', duration=0.5)
animRpm.start(self.rpm)
class Car(Scatter):
carImage = StringProperty("car362/car.png")
driverDoorClosedImage = StringProperty("car362/driverClosedDoor.png")
driverDoorOpenedImage = StringProperty("car362/driverOpenedDoor.png")
passangerDoorClosedImage = StringProperty("car362/passangerClosedDoor.png")
passangerDoorOpenedImage = StringProperty("car362/passangerOpenedDoor.png")
leftDoorClosedImage = StringProperty("car362/leftClosedDoor.png")
leftDoorOpenedImage = StringProperty("car362/leftOpenedDoor.png")
rightDoorClosedImage = StringProperty("car362/rightClosedDoor.png")
rightDoorOpenedImage = StringProperty("car362/rightOpenedDoor.png")
doorsStates = NumericProperty(0)
size = (286, 362)
def __init__(self, **kwargs):
super(Car, self).__init__(**kwargs)
_car = Image(source=self.carImage, size=self.size)
self.driverDoorOpened = Image(source=self.driverDoorOpenedImage, size=self.size)
self.passangerDoorOpened = Image(source=self.passangerDoorOpenedImage, size=self.size)
self.leftDoorOpened = Image(source=self.leftDoorOpenedImage, size=self.size)
self.rightDoorOpened = Image(source=self.rightDoorOpenedImage, size=self.size)
self.driverDoorClosed = Image(source=self.driverDoorClosedImage, size=self.size)
self.passangerDoorClosed = Image(source=self.passangerDoorClosedImage, size=self.size)
self.leftDoorClosed = Image(source=self.leftDoorClosedImage, size=self.size)
self.rightDoorClosed = Image(source=self.rightDoorClosedImage, size=self.size)
self.add_widget(_car)
self.add_widget(self.driverDoorOpened)
self.add_widget(self.passangerDoorOpened)
self.add_widget(self.leftDoorOpened)
self.add_widget(self.rightDoorOpened)
self.bind(doorsStates=self._update)
def _update(self, *args):
driverDoorStates = self.doorsStates&1
passangerDoorStates = self.doorsStates&4
leftDoorStates = self.doorsStates&16
rightDoorStates = self.doorsStates&64
if driverDoorStates != 0:
try:
self.remove_widget(self.driverDoorOpened)
self.add_widget(self.driverDoorClosed)
except:
pass
else:
try:
self.remove_widget(self.driverDoorClosed)
self.add_widget(self.driverDoorOpened)
except:
pass
if passangerDoorStates != 0:
try:
self.remove_widget(self.passangerDoorOpened)
self.add_widget(self.passangerDoorClosed)
except:
pass
else:
try:
self.remove_widget(self.passangerDoorClosed)
self.add_widget(self.passangerDoorOpened)
except:
pass
if leftDoorStates != 0:
try:
self.remove_widget(self.leftDoorOpened)
self.add_widget(self.leftDoorClosed)
except:
pass
else:
try:
self.remove_widget(self.leftDoorClosed)
self.add_widget(self.leftDoorOpened)
except:
pass
if rightDoorStates != 0:
try:
self.remove_widget(self.rightDoorOpened)
self.add_widget(self.rightDoorClosed)
except:
pass
else:
try:
self.remove_widget(self.rightDoorClosed)
self.add_widget(self.rightDoorOpened)
except:
pass
class Gauge(Scatter):
unit = NumericProperty(1.125)
zero = NumericProperty(116)
value = NumericProperty(10) #BoundedNumericProperty(0, min=0, max=360, errorvalue=0)
size_gauge = BoundedNumericProperty(512, min=128, max=512, errorvalue=128)
size_text = NumericProperty(10)
file_gauge = StringProperty("")
def __init__(self, **kwargs):
super(Gauge, self).__init__(**kwargs)
self._gauge = Scatter(
size=(self.size_gauge, self.size_gauge),
do_rotation=False,
do_scale=False,
do_translation=False
)
_img_gauge = Image(source=self.file_gauge, size=(self.size_gauge, self.size_gauge))
self._needle = Scatter(
size=(self.size_gauge, self.size_gauge),
do_rotation=False,
do_scale=False,
do_translation=False
)
_img_needle = Image(source="arrow512.png", size=(self.size_gauge, self.size_gauge))
self._gauge.add_widget(_img_gauge)
self._needle.add_widget(_img_needle)
self.add_widget(self._gauge)
self.add_widget(self._needle)
self.bind(pos=self._update)
self.bind(size=self._update)
self.bind(value=self._turn)
def _update(self, *args):
self._gauge.pos = self.pos
self._needle.pos = (self.x, self.y)
self._needle.center = self._gauge.center
def _turn(self, *args):
self._needle.center_x = self._gauge.center_x
self._needle.center_y = self._gauge.center_y
a = Animation(rotation=-self.value*self.unit self.zero, t='in_out_quad',duration=0.05)
a.start(self._needle)
class requestsLoop(Thread):
def __init__(self):
Thread.__init__(self)
self.daemon = True
self.start()
canCommands = [
can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_DOORS_COMMAND'] >> 8, messageCommands['GET_DOORS_COMMAND'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False),
can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_SPEED'] >> 8, messageCommands['GET_SPEED'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False),
can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_KM_LEFT'] >> 8, messageCommands['GET_KM_LEFT'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False),
can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_RPM'] >> 8, messageCommands['GET_RPM'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False),
can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_OIL_TEMPERATURE'] >> 8, messageCommands['GET_OIL_TEMPERATURE'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False),
can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_FUEL_LEFT'] >> 8, messageCommands['GET_FUEL_LEFT'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False),
can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_OUTDOOR_TEMPERATURE'] >> 8, messageCommands['GET_OUTDOOR_TEMPERATURE'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False),
can.Message(arbitration_id=0x746, data=[0x03, 0x22, messageCommands['GET_INDOOR_TEMPERATURE'] >> 8, messageCommands['GET_INDOOR_TEMPERATURE'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False),
can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_COOLANT_TEMPERATURE'] >> 8, messageCommands['GET_COOLANT_TEMPERATURE'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False),
can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_TIME'] >> 8, messageCommands['GET_TIME'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False)
]
def run(self):
while True:
for command in self.canCommands:
bus.send(command)
time.sleep(0.005)
class BoxApp(App):
def build(self):
dashboard = Dashboard();
listener = CanListener(dashboard)
can.Notifier(bus, [listener])
return dashboard
if __name__ == "__main__":
# Send requests
requestsLoop()
_old_excepthook = sys.excepthook
def myexcepthook(exctype, value, traceback):
if exctype == KeyboardInterrupt:
print "Handler code goes here"
else:
_old_excepthook(exctype, value, traceback)
sys.excepthook = myexcepthook
# Show dashboard
BoxApp().run()
Алгоритм работы следующий, используется 3 потока:
- В главном потоке работаем с графическими элементы (спидометр, тахометр, часы, температуры и др) на экране
- Во втором потоке каждые 5 мс делаем опрос следующего датчика
- В третьем потоке слушаем CAN шину, получив ответ парсим его и обновляем соответствующий графический элемент
Работает стабильно, самый долгий процесс в разработке был связан с рисованием дизайна. На данный момент обкатываю решение и потихоньку пишу мобильное приложение для iOS, чтобы любой мог попробовать цифровую панель приборов.
Проект цифровой панель приборов открытый. Рад буду предложениям и комментариям!