timsa.ru

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

Beacon

import uasyncio as asyncio
from machine import Pin,ADC,PWM,UART
import utime
import math

uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
#uart = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
uart.init(bits=8, parity=None, stop=1)

async def readuart():
    while True:
        if uart.any():
            data = uart.read()
            print(data)
        await asyncio.sleep_ms(1000)

async def heartbeat():
    temp_sensor = ADC(4)
    while True:
        current_time = utime.localtime()
        hours = current_time[3]
        minutes = current_time[4]
        seconds = current_time[5]
        temp = 27 - (temp_sensor.read_u16() * 3.3 / (65535) - 0.706)/0.001721
        #print("{:02d}:{:02d}:{:02d} t={:3.1f}".format(hours, minutes, seconds, temp))
        uart.write("{:02d}:{:02d}:{:02d} t={:3.1f}".format(hours, minutes, seconds, temp))
        await asyncio.sleep_ms(60000)

async def ledlight():
    #led = Pin(25, Pin.OUT)
    led = PWM(Pin(25, Pin.OUT))
    led.freq(2048)
    
    start_value = 1
    end_value = 65535
    num_values = 100
    growth_factor = (end_value / start_value) ** (1 / (num_values - 1))
    decay_factor = (start_value / end_value) ** (1 / (num_values - 1))
    
    while True:
        for i in range(num_values):
            value = start_value * (growth_factor ** i)
            led.duty_u16(int(value))
            await asyncio.sleep_ms(int(500/num_values))
            
        for i in range(num_values):
            value = end_value * (decay_factor ** i)
            led.duty_u16(int(value))
            await asyncio.sleep_ms(int(500/num_values))
            
async def main():
    loop  =  asyncio.get_event_loop ()
    loop.create_task(heartbeat())
    loop.create_task(ledlight())
    loop.create_task(readuart())
    loop.run_forever ()

if __name__ == '__main__':
    asyncio.run(main())
 9   19 дн   python   raspberry
 6   21 д   raspberry

Ложь

Опять хочу обратиться к логике и на простом примере (замеченном в комментариях) показать, как важно уметь выбрать правильную точку зрения для формирования адекватных выводов о рассматриваемом вопросе.

Обычно, когда вам предлагают подумать о каком-то вопросе, вам задают и некую точку зрения, с которой вы этот вопрос должны рассмотреть. Так вот, люди, в силу своей ментальной немощи, склонны неудачно выбирать данную точку. Часто это не принципиально и проекционные лучи, проведенные из предложенной точки зрения на рассматриваемый вопрос, всё равно дают приемлемую проекцию на «плоскость» ответов. Но иногда точка зрения выбирается так, что проекции просто не получается или получается вводящая в заблуждение херня.

Причем бывает, что люди упорствуют в консервации неудачной точки зрения, порождая гигабайты текста и защищая диссертации, пытающиеся объяснить, что же за херня получилась и какое значение она имеет. Одним из примеров служит известный «парадокс лжеца»: утверждение «это высказывание ложно» парадоксально, т. к. если высказывание истинно, то, т. к. оно утверждает обратное, оно ложно, что является парадоксом, а если оно ложно, то, т. к. оно соответствует тому, что утверждает, оно истинно, что тоже является парадоксом. Понятно?

И история обсуждений этой «великой загадки» насчитывает тысячи лет. Не самые глупые (но и не самые умные) люди на полном серьезе утверждают, что это «самореференция» и потому, дескать, вылез такой «парадокс». А в русской Вики вообще декларируется, что этот «парадокс» «стал основополагающим объектом исследования современной логики» (с). И даже некий Jc Beall недавно написал наукообразную статью с разбором сей великой загадки (будучи, правда, не ученым, а философом).

Давайте для начала поймем, что такое определение «истинности» или «ложности» высказывания. Обратимся к математическому формализму, т. к. он удобен и лаконичен. Для определения истинности высказывания необходимо задать логическую функцию, которая будет получать на вход определенные структурой этой функции аргументы, применяя к ним логические операторы, и выдавая значение — «истина» или «ложь». Например, для определения истинности того, пил ли я кофе с печеньем, надо задать функцию «Пил ли Полдень кофе с печеньем(„Полдень пил кофе“,„Полдень ел печенье“)»=«Полдень пил кофе»И«Полдень ел печенье». Всё просто.

Теперь вернемся к загадке истинности высказывания «это высказывание ложно». Вопрос, который у вас должен сразу возникнуть — как задана логическая функция, вычисляющая истинность? Само по себе высказывание функцией не является, ни «самореферентной» (вернее рекурсивной), ни любой другой — функцию надо задать в явном виде. Давайте зададим.

Назовем функцию — «Это высказывание ложно()». Есть ли у нее аргументы, от которых зависит значение функции? Т. к. высказывание лишено контекста, то это фактически алгебраическая система с одним элементом, без операций и с одним отношением рефлексивности. Брать переменные, как-то влияющие на высказывание, неоткуда, соответственно, функция аргументов не имеет. Что это значит? Это значит, что значению функции не от чего зависеть — оно может быть задано только как константа, т. е. или «Это высказывание ложно()»=«истина» или «Это высказывание ложно()»=«ложь». Более того, рекурсивной, т. е. ссылающейся на саму себя, эта функция быть не может, т. к. по определению для рекуррентного задания функции необходимо, чтобы она обращалась к самой себе с другими значениями аргументов, а тут аргументов нет. Потому тут нет никакой «самореферентности».

Так истинно или ложно высказывание «это высказывание ложно»? Как зададите логическую функцию, так и будет. Собственно всё — этим исчерпывается вся философия данного мнимого «парадокса».

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

 12   1 мес   логика

Кеневин

Часто управленец пытается решать задачу неподходящим способом. Человек по фамилии Сноуден (не тот, другой) придумал модель Cynefin, по-нашему — Кеневин. Валлийское слово, примерно переводится как «среда обитания».

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

Очевидный домен

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

Осложненный домен

Есть проблема, и решение неочевидно, но поддается анализу. Нужны эксперты, они разберутся в данных, выберут подходящий вариант. Здесь может быть несколько решений, но все они логичны и объяснимы.
Например, оптимизировать налоги, написать код сортировки массива, выявить неисправность оборудования, создать архитектуру айтишной системы.
Подключи экспертов и получи решение.

Сложный домен

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

Хаотичный домен

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

Беспорядочный домен

Это когда вообще непонятно, в каком ты домене. Команда тупит, клиенты недовольны, начальство что-то требует.
Определи, в каком ты домене, потом действуй.

Зачем нужна модель Кеневин? Чтобы определить тип задачи и выбрать верный способ управления. Бессмысленно решать задачи, требующие проверки гипотез с помощью «наилучших отраслевых практик». Не сработает, даже если позвать сто экспертов.

Давайте теперь разберемся, как применяют модель. Вот менеджер Марианна. Ее команда готовится выкатить обновление приложения для курьеров. За пару дней до релиза кто-то замечает: карты загружаются медленнее обычного.

Вроде проблема простая: не хватает мощности серверов. Это легко проверить, надо посмотреть загрузку. Ой, да! Сервер не справляется. Решение очевидно: добавляют ресурсы, карты снова работают быстро.

Через час проблема возвращается. Значит, дело не только в мощности. Осложненная ситуация: требуется анализ. Марианна подключает разрабов, те смотрят логи. А-а-а, изменился алгоритм загрузки карт, сервер перегружен ненужными запросами. Решение найдено, разрабы правят код.

Все хорошо? Не-а. Теперь у части пользователей приложение вообще не запускается. Разрабы не понимают, в чем дело, аналитики тоже. Это уже сложная ситуация, причин может быть много. Нужно выдвигать гипотезы, тестировать. У Марианны глаза цвета спелой клубники. Тут команда выясняет, что проблема в несовпадении версий чего-то там. Разрабатывают патч, все в порядке.

Релиз в проде и... хаос! Продукт массово вылетает у пользователей, поддержка погребена под трехметровым слоем жалоб. В панике команда пытается исправить обновление, но все только ухудшается. Это хаотичная зона, действовать надо быстро. Марианна приказывает отключить проблемные функции, команда стабилизируют систему. Все начинают разбираться, что пошло не так. И вдруг... Ладно, оставим Марианну за этим занятием.

Важно не только решать проблемы, но и понимать, с чем именно ты имеешь дело. Простому — инструкция. Осложненному — эксперт. Сложному — эксперимент. Хаосу — быстрые действия.

 41   3 мес   pm   проектирование

ZigBee Flashing CC2531 CCDebugger

Чтобы прошить и юзать CC2531 по инструкции https://www.zigbee2mqtt.io/guide/adapters/flashing/flashing_the_cc2531.html понадобится немножко санкционки.

TI (Техасские Инструменты) огородились, так что пришлось все скачать и выложить локально.

CC debugger user guide
https://timsa.ru/cc2531/swru197h.pdf

Софт для программирования старой версии FLASH-PROGRAMMER — SmartRF flash programmer
https://timsa.ru/cc2531/flash-programmer-1.12.8.zip

Драйвер для CC Debugger SWRC212 — Cebal — CCxxxx Development Tools USB Driver for Windows x86 and x64
https://timsa.ru/cc2531/swrc212a.zip

Всякая хрень, которая тоже лежала под замком, но сейчас мне не нужна

Более новая версия FLASH-PROGRAMMER-2 — SmartRF Flash Programmer v2
https://timsa.ru/cc2531/flash-programmer-2-1.8.2.zip

SWRC328 — Qt 5.7.0 Source and Libraries for Windows (MSVC2013)
https://timsa.ru/cc2531/swrc328.zip

SWRC273 — SmartRF Flash Programmer 2 v1.4.0
https://timsa.ru/cc2531/swrc273c.zip

PACKET-SNIFFER — SmartRF™ Packet Sniffer 2.18.1
https://timsa.ru/cc2531/swrc045z.zip

Ну и до кучи сама прошивка координатора

https://timsa.ru/cc2531/CC2531ZNP-Prod.bin
https://timsa.ru/cc2531/CC2531ZNP-Prod.hex

 63   4 мес   cc2531   ti   zigbee

Лечим диск

Посыпались ошибки диска, а точнее:

Device: /dev/sdb [SAT], 20 Currently unreadable (pending) sectors

Запустим короткий тест

smartctl —test=short /dev/sdb

Подождем 2 минуты и посмотрим:

smartctl -a /dev/sdb

Нужны две строчки, размер сектора:

Sector Sizes: 512 bytes logical, 4096 bytes physical

512 байт и местоположение ошибки

1 Short offline Completed: read failure 70% 43114 3906988766

3906988766

Попробуем прямо туда что-нибудь записать в надежде что оно само при попытке записи сделает реалокацию бэдблока (сектор 512 байт, 20 секторов начиная с 3906988766):

dd if=/dev/zero of=/dev/sdb bs=512 count=20 seek=3906988766 conv=noerror,sync

В моем случае сказало — хуй:

dd: error writing ’/dev/sdb’: Input/output error

Попробуем поискать их утилиткой берем расширенный диапазон вокруг проблемного места:

badblocks -b 512 -sv /dev/sdb 3907000000 3906970000
Checking blocks 3906970000 to 3907000000
Checking for bad blocks (read-only test): 3906988760ne, 0:00 elapsed. (0/0/0 errors)
...
done
Pass completed, 16 bad blocks found. (16/0/0 errors)

Нашли 16 секторов, попробуем их пометить:

badblocks -b 512 -svw /dev/sdb 3907000000 3906960000
Checking for bad blocks in read-write mode
From block 3906960000 to 3907000000
Testing with pattern 0xaa: done
Reading and comparing: done
Testing with pattern 0x55: done
Reading and comparing: done
Testing with pattern 0xff: done
Reading and comparing: done
Testing with pattern 0x00: done
Reading and comparing: done
Pass completed, 0 bad blocks found. (0/0/0 errors)

Проверим снова

smartctl —test=short /dev/sdb
smartctl -a /dev/sdb

Ну и заебись:

1 Short offline Completed without error 00% 43114  —

 35   4 мес   disc   linux

P2V на Proxmox

Ранее уже изучал этот вопрос с переездом на ESXi, но с тех пор от продуктов vmware давно отказался https://timsa.ru/all/p2v-ili-kak-preobrazovat-fizicheskiy-server-v-virtualny/

Сегодня будем мигрировать на proxmox.

Первый пункт — проверить, что знаешь пароль root и он подходит!

убрать лишние диски, иначе ВМка может не стартануть, а еще пароль рута не подходит...

vi /etc/fstab

настроить другой ip чтобы при старте она не обосрала жизнь старому серверу

vi /etc/network/interfaces

тут желательно остановить все активно пишущие на диск сервисы (mysql и influxdb как минимум)

скопировать образ системного диска (sdc) в файл (старенький SATA 3Gb/s дает 125 мб/с или 15 минут на 128 гигов)

dd if=/dev/sdc of=/mnt/somedisk/debra.img bs=8M conv=sync,noerror status=progress

вернуть лишние диски

vi /etc/fstab

вернуть ip

vi /etc/network/interfaces

конвертируем в qcow2 (заняло ровно час)

qemu-img convert -f raw debra.img -O qcow2 debra.qcow2

закидываем образ на proxmox 101 — это свободный номер для ВМ

scp debra.qcow2 root@pve:/root/vm-101-disk-0.qcow2

создаем машину (после создания ~можно~ нужно зайти в интерфейс и подрихтовать параметры)

qm create 101 --name oldphysical --memory 4096 --cores 4 --net0 virtio,bridge=vmbr0

импортируем диск (он полюбому копируется и даже немного конвертируется)

qm importdisk 101 /root/vm-101-disk-0.qcow2 local --format qcow2

подключаем диск (на предыдущем шаге будет точно написан путь local.., взять оттуда так как в интернете херня)

qm set 101 --scsi0 local:101/vm-101-disk-0.qcow2

ставим загрузочное устройство

qm set 101 --boot order=scsi0

запускаем машину

qm start 101

Также полезное

посмотреть содержимое образа raw

сначала команда выдаст устройство, например /dev/loop0

losetup -f --show debra.img

можно посмотреть разделы

fdisk -l /dev/loop0

подключим разделы

partprobe /dev/loop0

смонтируем первый

mount /dev/loop0p1 /mnt/restore

размонтируем

umount /dev/loop0p1

отключаем

losetup --detach /dev/loop0

посмотреть содержимое образа qcow2

проверяем что модуль nbd загружен

modprobe nbd max_part=8

коннектим устройство

qemu-nbd --connect=/dev/nbd0 debra.qcow2

смонтируем

mount /dev/nbd0p1 /mnt/restore

размонтируем

umount /dev/nbd0p1

отключаем

qemu-nbd --disconnect /dev/nbd0
 70   4 мес   linux   proxmox   virtualization

Proxmox default

bios: ovmf (зайти в биос F2 при старте и снять крестик с Secure boot, у меня было disabled)

efidisk0: local-lvm:vm-210-disk-0,efitype=4m,pre-enrolled-keys=1,size=4M

machine: q35

scsihw: virtio-scsi-single (подоткнуть iso образ VirtIO с драйверами https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/ если винда), поставить галочки Discard и SSD emulation, снять галочку IO thread

на самом гипервизоре в /etc/lvm/lvm.conf сделать issue_discards = 1 и выполнить fstrim -av

 35   4 мес   proxmox
 40   4 мес   soft
Ранее Ctrl + ↓