Моя записная книжка. Комментарии отключены из-за спама. Для вопросов используйте эту страничку

Позднее Ctrl + ↑

Умный дом с Алисой от Яндекса

Решил прикрутить к своему умному дому голосовой интерфейс от Яндекса. Мой умный дом — страшный зверинец из разных систем, на разном железе и разном софте.
В нем всё самописное, поэтому открытых дверей ждать не приходится.

Яндекс предполагает работу с нормальными сторонними сервисами, которые не поленились встроить регистрацию пользователей через OAuth. У меня такой нет, поэтому будем использовать яндексовскую же.

  1. Идем на https://oauth.yandex.ru/ и нажимаем зарегистрировать новое приложение.
    Название, описание, иконка — пофигу
    Ссылка на приложение тоже, но я задал путь к скрипту, обрабатывающему запросы яндекса.
    Платформы — веб-сервисы
    Callback URI ставим «https://social.yandex.net/broker/redirect» (это самое главное). Всякие ошибки «redirect_uri не совпадает с Callback URL» — это отсюда.
    Дальше доступы отмечаем
    API Яндекс.Паспорта доступ к электронной почте (может и не надо, но не жалко)
    Умный дом Яндекса ставим обе галочки.
    Сохраняем.
    Теперь у нас есть ID и Пароль.
  1. Идем на Яндекс диалоги https://dialogs.yandex.ru/developer выбираем новый диалог — создать умный дом
    Настройки:
    задаем любое название;
    endpoint url — самое главное — это опять путь к скрипту, который будет общаться с яндексом;
    тип доступа — приватный;
    подзаголовок пофигу что
    имя разработчика также
    описание тоже;
    иконку — любую картинку;
    авторизация — тут сложнее:
    идентификатор — вышеполученный ID
    секрет — вышеполученный Пароль
    URL авторизации — https://oauth.yandex.ru/authorize
    URL получения токена — https://oauth.yandex.ru/token
    обновление не нужно
    идентификатор группы действий (scope) пишем — login:email iot:control iot:view
    это те самые доступы, как они описаны внутри системы. Без этого будем получать ошибку «Не удалось определить список запрашиваемых доступов (invalid_scope)».
    Кстати чтобы их узнать можно пойти по ссылке https://oauth.yandex.ru/client/ID/info где ID — тот самый ID приложения.
    Сохраняем.
  1. Нажимаем «Опубликовать», ошибок быть не должно. Переключаем движок на «Опубликовано» и идем в Тестирование.
    Нажимаем большой плюс, выбираем «Другое устройство». Где то тут оно пробросит нас на авторизацию OAuth попросит разрешения предоставить данные и добавит умный дом в список производителей.
  1. Теперь идем в свой скрипт и начинаем прописывать устройства и их реакции.
    Тут придется сначала изучить https://yandex.ru/dev/dialogs/alice/doc/smart-home/about.html
 401   2021   alice   smarthome   yandex   умный дом

Распределительный шкаф

Schneider Electric PRAGMA 3x18 модулей встраиваемый щит PRA24318 = 13609р

Высота, мм 630
Ширина, мм 486
Глубина, мм 130

Schneider Electric PRAGMA 3x24 модулей встраиваемый щит PRA24324 = 34232р

Ширина 610 mm
Высота 630 mm wall
660 mm outside
Глубина 95 mm wall
55 mm outside

 268   2020   стройка

Зачем нужно высшее образование

Диплом ВУЗа показывает, что человек уже взрослый. Он может в 17 лет начать дело длиной 6 лет и успешно его завершить. Тем, кто не учился в ВУЗе, гораздо сложнее это доказать. Особенно на старте карьеры.

Столичный ВУЗ для людей из провинции — способ заявить о себе и вырваться из болота. Одно дело приехать сразу после школы и развиваться параллельно с получением знаний. Совсем другое — приехать в 35 лет со всем багажом, который обычно накапливается к этому возрасту, и начинать с полного нуля. Зачем выбирать более сложную стратегию?

Есть профессии, в которых почти невозможно преуспеть без высшего образования. Физика, математика, медицина. Конструирование ракет.

Инфоцыгане толкают идею, что все люди — креативные и талантливые, а ВУЗ отнимает у них драгоценное время. На самом деле большинство людей — ленивые и посредственные. Это нормально. Им нужен ВУЗ, чтобы найти себя. Или хотя бы начать искать.

Не можете совмещать образование и работу? Значит, не смогли договориться с работодателем, с вузом, выстроить удобные для всех процессы. Не смогли расставить приоритеты задач. Чем тут гордиться-то?

ВУЗ кажется скучным, не имеющим отношения к будущей работе? Вас же туда не силком тащили. Меняйте.

А приводить в пример Тинькова, Брэнсона, Цукерберга и им подобных — типичная ошибка выжившего.

Высшее образование — это про умение брать обязательства и выполнять договоренности.
А качественное образование еще и думать учит.

 99   2020   бизнес

Умный дом

Изучил шнайдеровский Zelio Logic, сяомишный Zigbee, сименсовский logo. В итоге решил поддержать отечественного производителя ОВЕН.

Для управления светом понадобится ПР102-230.2416.01.1 (цена 9960р), если не хватит 24/16 каналов то модуль расширения ПРМ-220.1 (цена 4560р) добавит 8/8 каналов. И возможно для подключения к облаку ПЕ210-230 (цена 4350р).

Ширина ПР102 — 7 модулей на DIN-рейке
Ширина ПРМ-220.1 — 5 модулей на DIN-рейке

Все модули на 220 вольт, чтобы в случае форсмажора модуль можно было выбросить и соединить всё в щите напрямую.

 33   2020   diy   стройка   умный дом

МТО-1000АМ

Все экземпляры этого объектива требуют технической доводки.

Ослабить зажатие первого мениска до легкого прижатия пальцем кольца крепления

Снимаете стопора крепления кольца для зажатия первой линзы. Иногда они не отдаются и поэтому их придется высверлить сверлом 2мм. Налить немного спирта в прорезь кольца крепления первой линзы и легко постучать по объективу в районе этого кольца. Затем вставить приспособление для откручивания кольца и открутить его. Несколько раз провернуть в оправе и закрутить кольцо уже не обжимая ничем только ногтем пальца. С первой линзой закончили.

Проверить и закрепить главное зеркало оно ослабляется со временем

Крепление зеркала. Откручиваете сбоку стопора на задней крышке объектива и откручиваете крышку . Для этого объектив зажимают в токарном станке и откручивают с помощью кожанного ремня. Крышку надо предварительно обстучать текстолитовым молотком. Открутив крышку получите доступ с четырем креплениям зеркала. Их надо плотно обжать как правило они ослаблены , обжимать надо равномерно крест накрест . Крышку плотно закрутить на место предварительно смазав резьбу литолом или солидолом. При зажатии ориентироваться по следам от стопоров. Или перед разборкой сделать маленькие метки так проще. Конструкции объективов разных моделей объектива разные. На некоторых моделях надо снимать задний байонет на М42 он может держать крышку. Обязательно поставить стопора на место.

 152   2020   фото

Ликбез: менеджер проектов vs менеджер продуктов

​Люди из непродуктовых компаний часто спрашивают, чем отличаются менеджер проектов (Project Manager) и менеджер продуктов (Product Manager). 

Представьте: вы зашли в ресторан. Ресторан хороший, вы лично знаете хозяина и уверены, что все готовится из свежайших продуктов, по лучшим рецепта и с соблюдением всех гигиенических норм. Вы знаете, что блюда приготовлены правильно.
Задумчиво листаете меню и вдруг понимаете, что просто хочется сладенького. Вы покидаете ресторан, покупаете себе мороженое в ближайшем киоске и радуетесь солнечной погоде.

Несмотря на то, что в ресторане блюда приготовлены правильно, вам сейчас они не подошли. Для вас это неправильные блюда. А мороженое — подходящее, правильное.

Разница между менеджером продукта и менеджером проекта примерно такая же, как между понятиями «сделать правильный продукт» и «сделать продукт правильно». 

Когда создается что-то новое — компьютерная игра, гоночный автомобиль, онлайн-сервис выдачи кредитов, смартфон, — то открывается проект. Собирается проектная команда и назначается менеджер проекта. Он будет отвечать за то, что в результате проекта получится продукт с согласованными заранее свойствами.  
Машина сможет разгоняться до 1500 км/ч, смартфон будет со встроенным счетчиком Гейгера, а для получения кредита не понадобится никаких документов вообще. Менеджер проекта будет отвечать за то, что этот продукт появится на рынке 1 января 2030 года, а перерасход бюджета не будет значительным. ) 

Менеджер проекта отвечает за то, что продукт будет создан правильно.

Но рынок может не принять этот продукт. Машине негде будет разгоняться до такой скорости, счетчик Гейгера будет тиканьем раздражать владельца смартфона, а банк разорится, выдавая кредиты без документов. Тогда окажется, что силы, время и деньги на проект потрачены зря. Но к менеджеру проекта никаких претензий. Он сделал то, что от него ждали — успешно завершил проект по созданию продукта с заданными свойствами.

Зато есть претензии к тому, кто отвечал за востребованность продукта рынком — менеджеру продукта. Именно он должен управлять свойствами продукта, чтобы продукт был успешен, а пользователи довольны.

Менеджер продукта отвечает за то, что будет создан правильный продукт.

Но менеджер продукта не отвечает за то, что продукт сделан правильно. Если вдруг у машины на презентации арабскому шейху (кто такую еще купит-то?) отвалится бампер, то все претензии к менеджеру проекта. Если к смартфону вместо счетчика Гейгера прикрутили фен, то вопросы к менеджеру проекта. 

Еще раз: менеджер проекта делает продукт правильно, а менеджер продукта делает правильный продукт.

Важно: менеджер проекта и менеджер продукта — это роли. Часто их совмещает один человек. Это разумно для больших продуктов, которые делает несколько продуктовых команд, как в Авито. Или для маленьких продуктов с одной командой — как в стартапах, для экономии.

Совмещать роли не обязательно — эти два типа менеджеров спокойно существуют в одном продукте, их зоны ответственности разделены. Менеджер продукта при этом — заказчик для менеджера проекта и его команды.       

Кто из них круче? Менеджер продукта много знает про юнит-экономику, метрики, умеет принимать сложные решения на основе данных и тюнинговать продукт, получая выдающиеся коммерческие результаты.)
Менеджер проекта умеет работать с людьми, ставить цели и достигать их в заданные сроки и бюджет, с нужным качеством.
Оба круты.

(c) Сергей Колганов aka http://t.me/psilonsk

 109   2020   проектирование

Отгадыватель кроссвордов

#!/usr/bin/env python3

import sys
from itertools import permutations
import re
import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import os.path

if len(sys.argv) < 4:
  print("Usage: \nwords.py yandex|google|filename|none алфавит маска\n")
  sys.exit()

search  = sys.argv[1]
alphabet = sys.argv[2]
pattern = sys.argv[3]

yandex = 'https://yandex.ru/search/?noreask=1&text='
google = 'https://www.google.ru/search?ie=UTF-8&hl=ru&spell=0&nfpr=1&q='

ua = UserAgent()
myheaders = {'User-Agent': str(ua.random), 'referer': 'https://www.google.ru'}

# все варианты перестановок
allwords = permutations(alphabet, len(pattern))

# выкидываем дубликаты
words = list(set(allwords))

# склеиваем 2-мерный список в одномерный
words2 = []
for word in words:
  str = ''.join(word)
  words2.append(str)

# проходим регекспом
obj = re.compile(pattern)
words = list(filter(lambda str: obj.search(str), words2))

print('Всего вариантов %d' % len(words))

output = []
wordlist = []

if os.path.exists(search):
  f = open(search, 'r', encoding = 'utf-8')
  wordlist = [line.strip() for line in f]
  f.close()
  print('Размер словаря %d' % len(wordlist))

for word in words:
  if search == 'google':
    r = requests.get(google + word, headers=myheaders)
    r.encoding = 'utf-8'
    soup = BeautifulSoup(r.text, 'html5lib')
    stat = soup.find('div', id='resultStats')
    if stat is not None:
      qty = re.search('Результатов:\sпримерно\s(.*)\s\(\d+,\d+\sсек.\)', stat.text)
      x = qty.group(1)
      x = x.split()
      x = ''.join(x)
      output.append([word, int(x)])
      print("%s - %s" % (word, x))
    else:
      output.append([word, 0])

  elif search == 'yandex':
    r = requests.get(yandex + word, headers=myheaders)
    r.encoding = 'utf-8'
    soup = BeautifulSoup(r.text, 'html5lib')
    stat = soup.find('div', {'class': 'serp-adv__found'})
    if stat is not None:
      qty = re.search('Нашлось\s(.*)\sрезультатов', stat.text)
      x = qty.group(1)
      output.append([word, x])
      print("%s - %s" % (word, x))
    else:
      output.append([word, 0])
      
  elif os.path.exists(search):
    if word in wordlist:
      output.append([word, 0])
    
  else:
    output.append([word, 0])

print('Отфильтрованно с помощью %s' % search)

output.sort(key=lambda x: x[1], reverse=True)

for str in output:
  print(str[0])

Как ставить задачи правильно

Хотите, чтобы что-то было сделано, — ставьте задачу. Если исполнитель вашу задачу не делает, то либо он негодяй, либо у вас нет полномочий ставить задачу этому человеку, либо вы ставите ее неправильно.

  1. Первое правило хорошо поставленной задачи — начните ее с глагола, а не с существительного.
    Плохо (отглагольное существительное):
    Тестирование модуля Х.
    Разработка функции Y.
    Хорошо (глагол):
    Протестировать модуль Х.
    Разработать функцию Y.
  1. Больше конкретики — конкретную задачу легче делать и проще контролировать. Задача создается, чтобы ответить на вопрос «что сделать?», а не «что делать?».
    Плохо (неконкретно):
    Обдумать риски в проекте А.
    Наметить дальнейшие шаги в проекте В.
    Хорошо (конкретно):
    Составить реестр рисков в проекте А.
    Создать план проекта В.
  1. Каждой задаче нужен срок исполнения. Нет дедлайна — нет стимула делать. Дедлайны дисциплинируют и помогают планировать.
    Плохо (нет срока):
    Создать документ D.
    Хорошо (есть срок):
    Создать документ D к 31.12.2020.
  1. Должны быть требования к результату. Нужно описать, что именно должно получиться, и что вообще считается выполненной задачей. Критерии выполнения — это важно.
  1. Описание должно включать все нужные для работы материалы. Исполнитель не должен бегать по разным источникам, по крупицам собирая информацию о задаче. Все, что ему нужно для выполнения, должно быть описано и приложено к задаче. То же касается любых ресурсов, которые нужны для выполнения задачи. Хочешь хорошего результата — создай человеку условия для работы.

Алфавит

A — Alfa
B — Bravo
C — Charlie
D — Delta
E — Echo
F — Foxtrot
G — Golf
H — Hotel
I — India
J — Juliett
K — Kilo
L — Lima
M — Mike​
​N — November
O — Oscar
P — Papa
Q — Quebec
R — Romeo
S — Sierra
T — Tango
U — Uniform
V — Victor
W — Whiskey
X — X-ray
Y — Yankee
Z — Zulu

 116   2020   abc   english   spelling

Подключаем Dadget CO2 к серваку

  1. Сначала сделаем чтобы любой пользователь мог обращаться к устройству
    создаем /etc/udev/rules.d/10-co2mon.rules
    с содержимым
ACTION=="add|change", SUBSYSTEMS=="usb", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="a052", MODE:="0666"

щелкаем

udevadm control --reload
udevadm trigger

проверяем что /dev/usb/hiddev0 теперь crw-rw-rw-

  1. Подключаем библиотечку PyUSB hid. PyUSB глючное говно вызывающее странные эффекты, например пропадение устройства hiddev0.
    pip3 install hid (или hidapi уже не помню, это гуглится)
  1. Читаем (алгоритм расшифровки передрал с сишного проекта co2mod)
#!/usr/bin/env python3

import hid
import time

def decode_co(data):
    # кручу-верчу
    data[0], data[2] = data[2], data[0]
    data[1], data[4] = data[4], data[1]
    data[3], data[7] = data[7], data[3]
    data[5], data[6] = data[6], data[5]
    
    result = bytearray(8)

    # всех обмануть хочу
    result[7] = ((data[6] << 5) & 0xFF) | ((data[7] >> 3) & 0xFF)
    result[6] = ((data[5] << 5) & 0xFF) | ((data[6] >> 3) & 0xFF)
    result[5] = ((data[4] << 5) & 0xFF) | ((data[5] >> 3) & 0xFF)
    result[4] = ((data[3] << 5) & 0xFF) | ((data[4] >> 3) & 0xFF)
    result[3] = ((data[2] << 5) & 0xFF) | ((data[3] >> 3) & 0xFF)
    result[2] = ((data[1] << 5) & 0xFF) | ((data[2] >> 3) & 0xFF)
    result[1] = ((data[0] << 5) & 0xFF) | ((data[1] >> 3) & 0xFF)
    result[0] = ((data[7] << 5) & 0xFF) | ((data[0] >> 3) & 0xFF)
    
    magic_word = b'Htemp99e'
    for i in range(8):
        r = ((magic_word[i] << 4) & 0xFF) | ((magic_word[i] >> 4) & 0xFF)
        if result[i] < r:
            result[i] = 0xFF - r + result[i]
        else:
            result[i] = result[i] - r

    # не знаю почему, но у меня проверка чек-суммы никогда не сходилась    
    #if result[0]+result[1]+result[2] != result[3]:
    #    return 0

    res = (result[1] << 8) + result[2]

    if result[0] == 0x42:
        print("T={0}".format(res * 0.0625 - 273.15))
        return 1
    elif result[0] == 0x50:
        print("CO={0}".format(res))
        return 2
    return 0
    
try:
    h = hid.device()
    h.open(0x04d9, 0xa052)

    # хз, не вникал
    h.set_nonblocking(1)

    # по идее это отправка некой magic_table которой шифруется ответ, но и без любой из этих строк работает
    #h.write(b'8\x00\x00\x00\x00\x00\x00\x00\x00')
    h.send_feature_report([0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
    time.sleep(0.05)

    co = 1
    t = 1
    while co | t:
        d = h.read(8)
        if d:
            n = decode_co(d)
            if n == 1:
                t = 0
            elif n == 2:
                co = 0

    h.close()

except IOError as ex:
    print(ex)
 219   2020   co2   dadget   driver   linux   python   программирование
Ранее Ctrl + ↓