Как стать автором
Обновить
32
0

Пользователь

Отправить сообщение

Спасибо за статью. Мастерски расковырял.

Сумел собрать для owrt тулзу sg_raw

Переключение работает. Только ttyUSB не светится. Видимо какой-то нестандартный serial девайс, который в винде ком портом светится, а в линуксе нет.

Может есть идеи куда копнуть?

Великолепно.

Вы сами видимо с процессом не знакомы. Мониторить можно и через SOZD, но что делать с нормативкой уровнем ниже? Есть еще regulation.gov.ru, да, но что делать с нормативкой еще ниже?

А самое главное, что на этот законотворческий процесс тратятся ресурсы. По моему личному опыту скажу, что из 100% времени на работу с документом, примерно 70% времени уходит, чтобы поднять по разным углам историю вопроса, наложить проект на текущую редакцию, а самый анализ и предложения когда делать? Вот за оставшиеся 30% времени и делать.

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

Да, пришлось повозиться прежде, чем кукурузник взлетел. Чексум просто первый попавшийся со stackoverflow. ) Там кто-то из буржуев так написал.

Там еще кое-что найти надо. Если поможете, будет здорово.

Там лежат и бинарники и скрипт по разборке на заголовки прелодер и бинарник самой программы.

https://github.com/legale/breed-mt7621-xiaomi-r3g.bin-reset-button-changer

Да, красивую надо найти. Или плату сфоткаю.

Так там даже grep кастрированный (без подсветки). Но никто не мешает взамен busybox утилит поставить полноценные.

А можно пример, когда systemd init сильно лучше простого init.d скрипта. Допускаю, что весь этот огород в systemd нагородили не от хорошей жизни. Тем не менее не перевариваю сложного, systemd бесит. Не могу сказать, что очень часто туда приходится ходить, но хорошо помню случай, когда я битый час просто искал откуда вызывается служба в systemd. Alpine очень полюбил, хотя он для десктопа пока слабо пригоден, тем не менее в качестве рабочего верстака использую именно этот дистрибутив. На одноплатных компьютерах для systemd вообще нет места.

А что за юридический термин такой «Никчемный договор». Это какой-то перевод с английского? А законов ты не знаешь. Есть такое понятие «конклюдентное действие», заключение договоров нажатием кнопок, подмигиванием, молчанием и т.п. это имменно конклюдентные действия. Достаточно составить оферту и написать там маленькими буквами, нажимая кнопку вы принимаете предложение о заключения договора. Именно так это и работает.
ГК РФ Статья 438. Акцепт
1. Акцептом признается ответ лица, которому адресована оферта, о ее принятии.
Акцепт должен быть полным и безоговорочным.
2. Молчание не является акцептом, если иное не вытекает из закона, соглашения сторон, обычая или из прежних деловых отношений сторон.


take it easy. Уже все придумано.
habr.com/ru/post/221539
Коллективный иск это только в кино. В России суд сейчас это просто пародия. Добиваться защиты там можно только, если уже совсем негде.
Я в последнее время в случае проблем сразу пишу матерный твит и в тот же миг служба SMM Билайна приходит на помощь и решает все мои вопросы. Я даже не звоню никуда и не разговариваю с роботом. Последний раз культурно наебали меня на Дальнем Востоке. Я был в командировке в Благовещенске с безлимитным тарифом Мегафона. За ночь мой баланс около 5к рублей обнулился, а утром я узнал, что Благовещенск не относится к зоне «Вся Россия» и тариф там, сколько-то рублей за килобайт. Обругал их и проклял. Вернулся в Мск и переключил номер на Билайн. Который всегда в случае спора со мной уступает. А я сохраняю лояльность и с ними уже который год.
Такие подписки у ОПСОСОВ это способ дополнительного заработка. Правовое государство, которое ты упомянул уже прикрыло кислород немного. Называется эта защита от лохотрона — отдельный счет для услуг контент-провайдеров. Включаешь его и случайный переход на лохотрон-сайт перестанет быть проблемой.
Статья очень занимательная. Пиши еще.
за 27 секунда человек не сможет. Скриптом даже сложно такое время сделать.
Проблема со спидометром. Время беру точное, а вот реальная скорость движения с учетом рендеринга меняется в результате скорость выдает иногда с большим отклонением. Надо подумать как еще повысить точность.
Добавил автопилоту «человечности», передача управляющих команд происходит с интервалом 1мс, без интервала автопилот может парковаться на сумашедших скоростях.
Код получился сложнее, но работает гораздо лучше.
m = {

sleep: function (ms) {
return new Promise(resolve => setTimeout(resolve, ms));
},

round: function (f, digits = 0) {
if (digits) {
let multiplier = Math.pow(10, digits);
return Math.round((f + Number.EPSILON) * multiplier) / multiplier;
} else {
return Math.round(f);
}
},

press: async function (code, cnt = 1) {
let lookup_tbl = {
'e': 69, 'q': 81, 'a': 65, 'd': 68, 'w': 87, 's': 83,
'left': 37, 'up': 38, 'right': 39, 'down': 40,
'<': 103, '>': 105
};

let e1 = new Event('keydown');
let e2 = new Event('keyup');
e1.keyCode = lookup_tbl[code];
e2.keyCode = lookup_tbl[code];
//кол-во повторений
while (cnt--) {
document.dispatchEvent(e1);
document.dispatchEvent(e2);
await this.sleep(1);
}
},

get_state: function (s) {
let o = window.document.getElementById(s);
let v1 = o.children[0].innerHTML;
let v2 = o.children[1].innerHTML.split(' ')[0];
v1 = parseFloat(v1);
v2 = parseFloat(v2);
return {'offset': v1, 'speed': v2, 'offset_abs': Math.abs(v1), 'speed_abs': Math.abs(v2)}
},

get_xyz: function () {
let x = window.document.getElementById('x-range');
let y = window.document.getElementById('y-range');
let z = window.document.getElementById('z-range');
x = x.children[0].innerHTML.split(' ')[0];
x = parseFloat(x);

y = y.children[0].innerHTML.split(' ')[0];
y = parseFloat(y);

z = z.children[0].innerHTML.split(' ')[0];
z = parseFloat(z);

return {'x': x, 'y': y, 'z': z, 'x_abs': Math.abs(x), 'y_abs': Math.abs(y), 'z_abs': Math.abs(z)}
},
/*
логика такая: включаем наблюдателя, ловим изменение значение и замеряем скорость,
ловим 2 раз и определяем скорость, отключаем наблюдателя и возвращаем результат
в промис.
*/
calc_pos: async function (axis) {
let el = window.document.getElementById(axis + '-range').children[0];
let t1, t2, tt1, tt2, v1, v2, ms, speed, counter = 0;

//отслеживать изменения значений будем через наблюдателя
//callback функция для наблюдателя
return new Promise(resolve => {

let callback = (mutationsList, observer) => {
let m = mutationsList[0];
let ischanged;
//если у нас уже есть t1
//отловим изменение скорости на 2 единицы, чтобы
//вычисления были точнее
//ловить будем только, если что-то поменялось
try {
ischanged = m.addedNodes[0].nodeValue !== m.removedNodes[0].nodeValue;
} catch (e) {
//pass
}

if (ischanged) {
let islowspeed = t1 && (performance.now() - t1) >= 1300;
if (counter == 40 || islowspeed){
t2 = performance.now();
v2 = m.addedNodes[0].nodeValue;
v2 = parseFloat(v2.split(' ')[0]);
ms = t2 - t1;
speed = (v1 - v2) * 1000 / ms;
//вырубаем наблюдателя
observer.disconnect();
resolve(this.round(speed, 2));
} else {
//замер делаем только на первом цикле
if (!counter) {
t1 = performance.now();
v1 = m.addedNodes[0].nodeValue;
v1 = parseFloat(v1.split(' ')[0]);
}
//увеличиваем счетчик циклов
++counter;
}
}
//на случай, если скорость не изменяется в течение 5 секунд
if (!tt1) {
tt1 = performance.now();
//если не было ни одного изменения
} else if (!counter) {
tt2 = performance.now() - tt1;
if (tt2 > 5000) {
//вырубаем наблюдателя и возвращаем 0
observer.disconnect();
resolve(0);
}
}
};

let observer = new MutationObserver(callback);

observer.observe(el, {
characterData: false,
childList: true,
attributes: false
});
});

},

//возвращает нужный ключ массива и его порядковый номер
get_idx: function (a, val, column = 0) {
if (isNaN(val)) {
return null;
}
for (let i = 0; i < a.length; ++i) {
//если значение меньше ключа, значит мы у цели
if (a[i][column] > val) {
//предыдущий индекс(если есть) и есть искомый ключ
i = i > 0 ? i - 1 : i;
return i;
}
}
//если ничего лучше нет, отдаем последний индекс
return a.length - 1;
},

flip_obj: function (table) {
res = {}
let keys = Object.keys(table);
for (let i = 0, len = keys.length; i < len; ++i) {
let key = keys[i];
res[table[key]] = key;
}
return res;
},

//таблица скоростей и соответствующих им расстояний до точки начала координат
lookup_table: [
[0, 0],
[0.01, 0.2],
[0.02, 0.5],
[0.05, 1.5],
[0.1, 2],
[0.15, 2.5],
[0.2, 3],
[0.3, 3.5],
[0.35, 5],
[0.4, 5.5],
[0.5, 6],
[0.55, 10],
[0.6, 20],
[0.65, 30],
[2.2, 80],
[3, 120],
[4, 150],
],

adjust_pos: async function (axis, speed = null) {
//соответствие осей и кнопок управления по осям
let ss = {'x': ['q', 'e'], 'y': ['d', 'a'], 'z': ['w', 's']}
if (this.abort) {
return null;
}

//получаем данные о положении
let pos = this.get_xyz();
//таблица подстановки вектора скорости движения и положения на оси относительно 0
let lookup_table = this.lookup_table;

//рабочий цикл будет включаться только при наличии данных о векторе скорости
if (speed !== null) {
//console.log('axis:', axis, 'speed:', speed, 'pos:', pos[axis]);

//получаем индекс положения корабля на оси
//расстояния в таблице подстановок только положительные, поэтому берем
//расстояние по модулю. расстояния в колонке 1 таблицы
let pos_idx = this.get_idx(lookup_table, pos[axis + '_abs'], 1);

//теперь получаем индекс из таблицы векторов скорости
//если положение корабля отрицательное к нулю,
//перевернем вектор скорости, чтобы отрицательные значения движения к нулю
//были положительными
if (pos[axis] < 0) {
speed = -speed;
}

//берем значение скорости и смотрим по таблице
//скорости в нулевой колонке
let speed_idx = this.get_idx(lookup_table, Math.abs(speed), 0);
//если хотя бы одного индекса нет, выходим
if (pos_idx === null || speed_idx === null) {
console.log('error! pos_idx or speed_idx not found.');
return false;
}
//console.log('speed:', speed, 'speed_idx:', speed_idx, 'pos_idx:', pos_idx);
//теперь мы можем определить направление и число импульсов
//для каждого расстояния есть желаемая скорость.
//для расстояния 0 скорость 0, для расстояния 0.5, скорость 0.02
//кол-во импульсов вычисляется исходя из того, что импульс = 0.02м/с
//формула: impulse = Math.floor(speed - lookup_table[pos_idx][0]) / 0.02)
//т.е. вычитая из текущей скорости желаемую скорость, мы определяем
//скорость которую надо прибавить или отнять, чтобы получить нужную
//делим на 0.03 (скорость 1 импульса) и получаем кол-во импульсов

//если отклонение от нужной скорости до 5%, ничего не делаем
let diff = speed - lookup_table[pos_idx][0];
let diff_percent = Math.abs(diff / lookup_table[pos_idx][0]);
if( diff_percent > 0.05) {

let impulse = Math.floor(diff / 0.03);

//направление импульса зависит от 2 вещей: направления вектора скорости,
// положение корабля относительно 0 осевой точки
//это индексы направлений импульса
let directions = {'1': 0, '-1': 1, '0': 0};

//определяем направление импульса
let direction = Math.sign(impulse) * Math.sign(pos[axis]);
//определяем кнопку
direction = directions[direction.toString()];
let key = ss[axis][direction]

//передаем импульс, если отклонение от нужной скорости более 5%
console.log('axis:', axis, 'speed:', speed, 'key:', key, impulse);
if(Math.abs(impulse) >= 200){
console.log('impulse >= 200, skip.', impulse);
}else {
await this.press(key, Math.abs(impulse));
}
}
}

//запускаем себя заново с данными о скорости
return this.calc_pos(axis).then(speed => this.adjust_pos(axis, speed))
},
//этим методом и производится автоматическая стыковка корабля
autodock: async function (abort = false) {
this.abort = abort;
this.adjust_pos('x');
this.adjust_pos('y');
this.adjust_pos('z');
this.adjust_axis();
},

adjust_axis: async function () {
let yaw = m.get_state('yaw');
let roll = m.get_state('roll');
let pitch = m.get_state('pitch');
let run = true;
while (run) {
if (this.abort) {
return null;
}
//console.log(yaw['offset'], pitch['offset'], roll['offset']);
if (yaw['offset'] > 0) {
m.set_axis('yaw', Math.sqrt(yaw['offset_abs'] / 10));
} else {
m.set_axis('yaw', -Math.sqrt(yaw['offset_abs'] / 10));
}
if (pitch['offset'] > 0) {
m.set_axis('pitch', Math.sqrt(pitch['offset_abs'] / 10));
} else {
m.set_axis('pitch', -Math.sqrt(pitch['offset_abs'] / 10));
}
if (roll['offset'] > 0) {
m.set_axis('roll', Math.sqrt(roll['offset_abs'] / 10));
} else {
m.set_axis('roll', -Math.sqrt(roll['offset_abs'] / 10));
}

await m.sleep(50);
yaw = m.get_state('yaw');
roll = m.get_state('roll');
pitch = m.get_state('pitch');
}

},

set_axis: async function (s, speed) {
speed = Math.round((speed + Number.EPSILON) * 10) / 10;
let ss = {'yaw': ['left', 'right'], 'roll': ['<', '>'], 'pitch': ['up', 'down']}
if (!(s in ss)) {
console.log(s + ' not in ', ss);
return;
}

let o = m.get_state(s);
speed *= 10
let cur_speed = o['speed'] * 10;
let distance = 0;

distance = speed - cur_speed;

if (distance > 0) {
while (distance--) {
m.press(ss[s][1]);
}
} else {
distance = Math.abs(distance);
while (distance--) {
m.press(ss[s][0]);
}
}
},

abort: false,

}

m.autodock();
//m.autodock(1); чтобы остановить автопилот
Выложи код сюда.
Пилот «принял на грудь». Идея классная, но реализация — дрянь. Код примитивный и работает очень плохо. Особенно убило, что умудряется провалить стыковку, даже когда уже полтора метра до шлюза осталось и можно просто откинуться в кресле.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность