Иногда требуется сделать хитрый тонкий клиент — с необычной авторизацией и минимумом затрат.

Проще всего для этого использовать Linux.

Для одноплатных пк на базе ARM широко распространен дистрибутив Armbian, который основан на Debian ветке.

Для экспериментов у меня в наличии была плата OrangePi One
image
и MicroSD карта на 2G — я решил сделать из этого тонкий клиент RDP с окном блокировки и без лишнего программного обеспечения.

Дистрибутив Armbian для этой платы здесь.

Качаем последний с пометкой:

Server or light desktop usage scenarios.

В нем не будет рабочего стола, который не нужен в тонком клиенте.

Записываем образ на MicroSD (я использовал sourceforge.net/projects/win32diskimager).

После записи: вставляем MicroSD, подключаем все интерфейсы (LAN, Дисплей, клавиатуру, мышь), подаем питание, ждем пока загрузится.

Когда система загрузилась появится предложение ввести логин и пароль. Также можно зайти по SSH глянув выданный DHCP адрес (я воспользовался этой возможностью чтобы не вбивать настройки с клавиатуры и запустил PuTTY).

Логин: root
Пароль: 1234

После входа система попросит сменить пароль: вводим текущий 1234 и два раза новый пароль.

Также предлагается создать пользователя — назовем его user.

После этого приступим к настройке системы под задачу.

Установим недостающие пакеты:

apt update
apt install xorg lightdm xcursor-themes numix-gtk-theme numix-icon-theme 
apt install python-gtk2 freerdp

Запуск графического входа для systemd включется так:

systemctl set-default graphical.target

Создадим файлы:
(содать их проще всего с помощью редактора vi — после запуска с параметром нужно нажать i для вставки — потом просто вставить текст в окно консоли, а по завершении нажать Esc и набрать :w для записи и :q для выхода)

Для получения своих параметров через DHCP сервер

vi /etc/dhcp/dhclient-exit-hooks.d/paramscript

setup_add() {
    echo $new_host_name > /etc/hostname
    hostname $new_host_name

    if [ -z "$new_nds_servers" ] ; then
        echo $new_routers > /tmp/rdp_server
        echo "testuser" > /tmp/rdp_user
        echo "1234test#" > /tmp/rdp_passwd
    else
        echo $new_nds_servers > /tmp/rdp_server
        echo $new_nds_tree_name > /tmp/rdp_user
        echo $new_nds_context > /tmp/rdp_passwd
    fi
}

case $reason in
    BOUND|RENEW|REBIND|REBOOT)
        setup_add
        ;;
    EXPIRE|FAIL|RELEASE|STOP)
        return
        ;;
esac

этот скрипт получает по DHCP имя хоста и nds_servers, nds_tree_name, nds_context и сохраняет их значения в файлах во временной папке. По умолчанию будет использован IP адрес маршрутизатора.

Для настроек GTK и назначения его тем создадим

vi /home/user/.gtkrc-2.0

gtk-icon-theme-name = "Numix"
gtk-theme-name = "Numix"
gtk-cursor-theme-name = "whiteglass"

Для настройки менеджера графической среды LightDM:

vi /etc/lightdm/lightdm.conf

[LightDM]
greeter-user=user
[Seat:*]
greeter-session=my-greeter

я после экспериментов решил использовать greeter (программа входа), таким образом не придется настраивать автовход, а программа запустится от нужного пользователя.

Теперь создадим ярлык программы (и его папку):

mkdir /usr/share/xgreeters/
vi /usr/share/xgreeters/my-greeter.desktop

[Desktop Entry]
Name=PyGTK+ Greeter
Comment=This runs the PyGTK+ greeter, it should only be run from LightDM
Exec=python /home/user/greeter.py
Type=Application
X-Ubuntu-Gettext-Domain=lightdm

И сам код программы входа:

vi /home/user/greeter.py

Код предлагает ввести 4 значный пароль 0811 (месяц день с незначащими нулями без прбелов)
После успешного ввода запускается xfreerdp с полученными параметрами.

Код
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from datetime import datetime
from gobject import timeout_add
import os,sys,gtk,pango,subprocess

class GreeterApp:
	def __init__( self ):
		self.builder = gtk.Builder()
		#self.builder.add_from_file("ui.glade")
		self.builder.add_from_string(ui)
		self.window = self.builder.get_object ("window")
		self.pass_field = self.builder.get_object ("pass_field")
		self.passct = self.builder.get_object ("pass")
		self.contrl = self.builder.get_object ("control")
		self.pass_field.modify_font(pango.FontDescription('Sans Bold 36'))
		self.passwd = datetime.now().strftime("%m%d")
		self.rdp_server = open("/tmp/rdp_server").read().split(',')[0]
		self.rdp_user = open("/tmp/rdp_user").read()
		self.rdp_passwd = open("/tmp/rdp_passwd").read()
		self.process = None
		timeout_add(5000, self.timeout)
		if self.window:
			self.window.connect("destroy", gtk.main_quit)
			self.contrl.set_visible(False)
			self.window.set_size_request(gtk.gdk.screen_width(),gtk.gdk.screen_height())
		self.builder.connect_signals(self)
	def hide(self, widget):
		self.contrl.set_visible(False)
		self.passct.set_visible(True)
		self.window.move(0,0)
		self.window.set_size_request(gtk.gdk.screen_width(),gtk.gdk.screen_height())
		if self.process:
			self.process.terminate()
			self.process = None
	def timeout(self):
		if self.window:
			self.window.set_keep_above(True)
			self.window.set_modal(True)
		return True
	def check_pass(self, widget):
		if self.pass_field.get_text() == self.passwd:
			self.pass_field.set_text("")
			self.passct.set_visible(False)
			self.contrl.set_visible(True)
			self.window.set_size_request(50,50)
			self.window.move(0,gtk.gdk.screen_height()-50)
			#sys.exit()
			self.process = subprocess.Popen(["xfreerdp","/v:"+self.rdp_server,"/f","/cert-ignore","/u:"+self.rdp_user,"/p:"+self.rdp_passwd])
	def clear_pass(self, widget):
		self.pass_field.set_text("")
	def num_press(self, widget):
		self.pass_field.set_text(self.pass_field.get_text()+widget.get_tooltip_text())
	def on_destroy(self, widget):
		sys.exit()
if __name__ == "__main__":
	settings = gtk.settings_get_default()
	#settings.props.gtk_button_images = True
	settings.props.gtk_enable_tooltips = False
	ui = """
<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk+" version="2.24"/>
  <object class="GtkWindow" id="window">
    <property name="can_focus">False</property>
    <property name="type">popup</property>
    <property name="title" translatable="yes">MyGreeter</property>
    <property name="resizable">False</property>
    <signal name="destroy" handler="on_destroy" swapped="no"/>
    <child>
      <object class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkHBox" id="control">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkButton" id="power1">
                <property name="use_action_appearance">False</property>
                <property name="width_request">50</property>
                <property name="height_request">42</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="hide" swapped="no"/>
                <child>
                  <object class="GtkImage" id="image4">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="stock">gtk-no</property>
                  </object>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkHBox" id="hbox1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkTable" id="pass">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="n_rows">6</property>
                <property name="n_columns">3</property>
                <child>
                  <object class="GtkEntry" id="pass_field">
                    <property name="width_request">240</property>
                    <property name="height_request">60</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="visibility">False</property>
                    <property name="invisible_char">?</property>
                    <property name="xalign">1</property>
                    <property name="invisible_char_set">True</property>
                    <property name="primary_icon_activatable">False</property>
                    <property name="secondary_icon_activatable">False</property>
                    <property name="primary_icon_sensitive">True</property>
                    <property name="secondary_icon_sensitive">True</property>
                  </object>
                  <packing>
                    <property name="right_attach">3</property>
                    <property name="bottom_attach">2</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_0">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">0</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_0">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">0</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="top_attach">5</property>
                    <property name="bottom_attach">6</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_1">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">1</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_1">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">1</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="top_attach">4</property>
                    <property name="bottom_attach">5</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_2">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">2</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_2">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">2</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                    <property name="top_attach">4</property>
                    <property name="bottom_attach">5</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_3">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">3</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_3">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">3</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">2</property>
                    <property name="right_attach">3</property>
                    <property name="top_attach">4</property>
                    <property name="bottom_attach">5</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_4">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">4</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_4">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">4</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="top_attach">3</property>
                    <property name="bottom_attach">4</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_5">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">5</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_5">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">5</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                    <property name="top_attach">3</property>
                    <property name="bottom_attach">4</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_6">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">6</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_6">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">6</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">2</property>
                    <property name="right_attach">3</property>
                    <property name="top_attach">3</property>
                    <property name="bottom_attach">4</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_7">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">7</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_7">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">7</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="top_attach">2</property>
                    <property name="bottom_attach">3</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_8">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">8</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_8">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">8</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                    <property name="top_attach">2</property>
                    <property name="bottom_attach">3</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_9">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="tooltip_text" translatable="yes">9</property>
                    <signal name="clicked" handler="num_press" swapped="no"/>
                    <child>
                      <object class="GtkLabel" id="l_9">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes">9</property>
                        <attributes>
                          <attribute name="weight" value="bold"/>
                          <attribute name="size" value="40000"/>
                        </attributes>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">2</property>
                    <property name="right_attach">3</property>
                    <property name="top_attach">2</property>
                    <property name="bottom_attach">3</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_ent">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <signal name="clicked" handler="check_pass" swapped="no"/>
                    <child>
                      <object class="GtkImage" id="image2">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="stock">gtk-yes</property>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                    <property name="top_attach">5</property>
                    <property name="bottom_attach">6</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="b_del">
                    <property name="use_action_appearance">False</property>
                    <property name="width_request">80</property>
                    <property name="height_request">80</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <signal name="clicked" handler="clear_pass" swapped="no"/>
                    <child>
                      <object class="GtkImage" id="image3">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="stock">gtk-no</property>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="left_attach">2</property>
                    <property name="right_attach">3</property>
                    <property name="top_attach">5</property>
                    <property name="bottom_attach">6</property>
                    <property name="x_options">GTK_SHRINK</property>
                    <property name="y_options">GTK_SHRINK</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">False</property>
                <property name="position">0</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">False</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>
	"""
	app = GreeterApp()
	app.window.show()
	gtk.main()


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

Комментарии (68)


  1. Gryphon88
    13.08.2018 18:15

    Немного жлобский вопрос: 1,2ГГц процессора и 512МБ памяти — это довольно много, 10 лет тому это был обычный офисный компьютер. Насколько часто сейчас на одноплатниках «толстые» рабочие места делают?


    1. Naves
      13.08.2018 18:29

      Пробовал на raspberry-pi-3-model-b
      Firefox безбожно тормозит на половине сайтов. Либреофис тоже тормозит.
      Вспомнил времена 486 компьютеров и Windows 95, скорость не изменилась. Все медленно и печально.


      1. Gryphon88
        13.08.2018 18:31

        Из бинарников ставили или пересобирали с -O3/Os? Браузеры (и тренды сайтостроительства) отдельная печальная тема.


        1. Naves
          13.08.2018 18:33

          Готовый Raspbian with Desktop. Пользоваться десктопом можно, но только от полной безысходности.


      1. Salavat
        13.08.2018 19:33

        Пользовался Orange Pi Plus 2E при переезде на другую работу 2 месяца до покупки компьютера. Подключался к офисному ПК. Всё отлично работало. Пользовался chromium. Даже FullHD фильмы смотрел. ОС Armbian, перенесенный во внутреннюю EMMC память. WI-FI встроенный все тянул нормально. Звук через колонки с питанием с него же по USB.


        Фото Orange Pi Plus 2E

        image


    1. KYuri
      13.08.2018 18:46
      +1

      Вполне юзабельно, если в качестве диска не использовать SD-карту.
      Тот же armbian позволяет «перенести» root на внешний диск, а с SD-карты грузить только ядро.
      А Raspberry Pi, начиная с третьей, вообще умеют загружаться с USB-storage, так что даже SD-карта не нужна.


      1. ivn86
        15.08.2018 07:41
        +1

        Raspberry Pi, начиная с третьей, вообще умеют загружаться с USB-storage

        Немаловажно, что Pi 3 получил загрузку по сети, а значит его можно использовать как тонкий клиент для LTSP-сервера. Без SD-карточек, без флешек. В 2015 году экспериментировал с Pi 1 B+ в качестве тонкого клиента для LTSP-сервера на базе Debian 7. Pi 1 B+ не умеет грузится по сети, поэтому приходилось велосипедить c Berryboot, а мощности процессора едва хватало для отрисовки картинки.


    1. soshnikov
      14.08.2018 02:33

      Ну так и требования изменились. Двадцать лет назад и двушка офис тянула вполне.
      С одноплатниками проблема с дровами. Особливо с видеодровами.


    1. Max-812
      14.08.2018 20:35

      Делают только под специализированное и оптимизированное ПО. Потому как обычное массовое и офисное ПО способно сожрать любое количество ресурсов без какой-либо практической пользы. :( Спасибо современному подходу к программированию, когда ради «hello world!» мы тащим 50 мегабайт библиотек на все случае жизни.


  1. Naves
    13.08.2018 18:19

    Пробовали freerdp не из репозиториев, а текущую версию с github? Проект довольно далеко уехал от версии 1.10


  1. EmmGold
    13.08.2018 18:29

    В конце надо флешку в RO сделать, динамические настройки в топку, на то они и динамические. Иначе флешка живёт не долго.


    1. fzn7
      13.08.2018 18:56

      Похоже на байку. У меня в наличии 15 распберри на которых крутятся spring-boot демоны. За полтора года с железом проблем 0, логи пишутся, sd карты не мрут


      1. sintech
        13.08.2018 19:15

        Какая модель sd карточек?


        1. fzn7
          13.08.2018 19:23

          Закупали комплекты «Малина» в Амперке. Они у них брендированные, выяснить фабрику затруднительно.


      1. edo1h
        14.08.2018 02:43

        у меня десятка два pi, raspbian. и больше сотни железок с openwrt, которые пишут данные на usb flash (буквально сотни килобайт в сутки).
        что microsd, что usb дохнут.

        переводим на ro + кольцевой буфер в NOR flash. иногда даже посещают мысли написать статью на хабр )
        в таком применении я бы делал чисто ro


        1. electronus
          14.08.2018 06:07

          SLC флешки пробовали?


          1. edo1h
            14.08.2018 12:43

            в куче сломанных есть и slc )


        1. nanshakov
          14.08.2018 11:42

          Было бы интересно почитать


        1. Magister7
          14.08.2018 12:38

          А где вы нашли NOR flash который можно подключить к raspberry pi? И сколько он стоит примерно?


          1. edo1h
            14.08.2018 12:52

            обычно у NOR flash интерфейс SPI, так что подключить не проблема.
            Мы используем флешку на 4 мегабайта, стоит порядка 100р.
            Гигабайтных NOR не делают AFAIK, большие объёмы — вотчина NAND.
            (зато у NOR 100к перезаписей и декларируется ненужность избыточного кодирования)


            1. Magister7
              14.08.2018 12:57

              Спасибо за информацию, тогда всё хорошо действительно.


            1. nafikovr
              16.08.2018 11:04

              странно это все. wearleveling на контроллерах sd/usb флешек должен за счет объема обеспечить время жизни больше чем у 4МБ NOR. похоже на косяки с ФС или контроллером флешки (что маловероятно, учитывая что флешки были разные)


        1. dlinyj
          14.08.2018 14:20

          Просим статью, очень просим. Несколько раз в разных областях нужна была инфа.


          1. edo1h
            14.08.2018 20:01

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

            про r/o систему на sd/usb же — там всё просто, рецептов в сети очень много, хотя если есть интерес — то могу написать, как это получилось у меня


            1. dlinyj
              15.08.2018 14:41

              r/o система и так понятна. Используем. Но буффер — это интересно. Если не сложно, опишите пожалуйста в отдельном посте.


        1. vzhicharra
          14.08.2018 15:22

          Конечно писать статью!
          Интересно будет многим!


  1. x893
    13.08.2018 19:48

    Для LORA шлюзов использую NanoPi с eMMC + DietPi.
    Прекрасно работают (без дисплея).


  1. galadhon
    14.08.2018 07:09

    WTWare же есть wtware.ru/index.html


    1. Naves
      14.08.2018 17:13

      Она для малинок внезапно стала платной. Хотя ожидаемо.


  1. Dioxin
    14.08.2018 07:27

    Без принтера все теряет смысл.


    1. lokkiuni
      14.08.2018 10:52

      Без локального принтера? Да вы, батенька, ретроград!


      1. Dioxin
        14.08.2018 11:54

        Это не я, а наше правительство которое денег на оборудование не дает.
        В этом году попытаюсь списать Pentium III.


        1. lokkiuni
          14.08.2018 12:06

          Сочувствую. Сам списывал лет 5 назад — но было проще, из блока питания во время работы вылетали искры))

          Тогда принтер в тот же хаб (он же надеюсь усб?) и настраивать уже самому — в условиях жесткой экономии, я думаю, труда не должно составить) Дальше либо расшарить и ловить терминальным сервером, либо если rdp-клиент умеет — пробрасывать в терминальную сессию.


        1. nitro80
          15.08.2018 01:35

          Сцуко, случайно влупил минус, а переголосовать нельзя :(


          1. acyp
            15.08.2018 04:32
            +1

            поправил :)


    1. m0rpheus
      14.08.2018 12:06

      А в чем проблема подключить принтер к одноплатнику? Например, у меня cubieboard2 спокойно принтсервером работает


      1. Gryphon88
        14.08.2018 14:30

        LPT или COМ разъём?


        1. Solexid
          14.08.2018 16:48
          +1

          Вы из 2000 нам пишете?


          1. Gryphon88
            14.08.2018 16:51

            Из госучреждения. Это сильно меняет мировоззрение.


            1. Solexid
              14.08.2018 17:04

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


              1. Gryphon88
                14.08.2018 17:10
                +2

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


                1. nitro80
                  15.08.2018 01:39

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


                  1. lokkiuni
                    15.08.2018 11:53

                    В крупных компаниях обычно к тому моменту успевают пол-механики сносить и не по разу.

                    Но подход гарантия кончилась — списываем — до сих пор вызывает муражки по коже…


          1. Naves
            14.08.2018 17:02
            +1

            Может он счастливый обладатель epson lx 300. Определенная часть людей ищет эмуляторы такого принтера, чтобы получать данные с древнего оборудования в компьютере вместо бумаги.
            Еще есть куча принтеров для печати на бланках и всяких этикетках, иногда они даже сейчас подключаются через COM.


            1. lokkiuni
              14.08.2018 18:09

              Ну предположим Com через usb работает уже в общем-то идеально.


            1. Meklon
              14.08.2018 18:18

              Этот матричный разве не через usb? У меня таких несколько десятков. Там есть LPT, но я его не использую.


              1. nafikovr
                16.08.2018 11:10

                на сколько понял там usb появился далеко не в первой ревизии матери. мы к нему вообще мультиплексную линию прикручивали >_<


        1. JerleShannara
          15.08.2018 03:00

          1) USB->COM/LPT (хз, не проверял как на LPT оно будет жить)
          2) Если COM, то пардоньте, я ARMов без USART-а ещё не видел, MAX в роли преобразователя уровней и готово.
          3) При желании LPT легко эмулируется на базе GPIO, вполне нормально себе выходило на Cortex-M0, правда в baremetal, в линуксе может какие-то грабли будут.

          Для вариантов 2 и 3 наверное потребуется перестройка дерева устройств или колдунство с uboot-ом.


          1. dlinyj
            15.08.2018 14:43

            А если требуется полный СОМ? :)


            1. JerleShannara
              16.08.2018 03:02

              В реалиях Cortex-M обычно пара портов бывает почти полноценных (нет RI), с Cortex-A я на фрискейле тоже обычно видел один порт с RTS/CTS(и оно даже работало), насчет DTE и прочих момедных сигналов не смотрел, нужды небыло.


          1. Gryphon88
            16.08.2018 01:21

            1) На LPT жить будет лучше, он простой как грабли. А вот СОМ может потребоваться полный, т.е. не только RX/TX, а ещё CTS/RTS (чтобы в принтерах использовались ещё carrier detect и ring signal не помню) — тут уже не всякий преобразователь вывезет. Ещё бывает, когда пинами дёргают как попало, поперёк стандарта, этакий аналог GPIO, такое позволяют WinXP и более ранние, и такую содомию я даже видел.
            2) Писать модуль ядра или работать поверх модуля gpio можно, но лениво.


            1. JerleShannara
              16.08.2018 03:04

              Если идем USB->COM, то даже чертов пролифик умеет, не говоря об FTDI и CP21xx.
              Если нам надо дёргать пинами вразнобой — то тогда уже идём в GPIO, т.к. умеет-ли мощный кортекс такое я хз.


            1. nafikovr
              16.08.2018 11:13

              USB-LPT как раз может быть проблема в некоторых режимах (ECP+DMA как минимум)


  1. klim76
    14.08.2018 08:41

    Смотрю на эту картинку и понимаю — нам срочно требуется mini(micro)-LAN port


    1. hokum13
      14.08.2018 10:25

      Чтобы патч-корды были в дифиците и стоили по 500 р. метр? Ненене Девид! А для тех, кому нужно потоньше есть wifi.


    1. dMac
      14.08.2018 10:42

      (уже отметили выше)
      Для такой мелкой, пардон, фигнюльки, более уместным будет WiFi (который там, кстати, есть).


  1. clawham
    14.08.2018 10:02

    все бы хорошо но нет VGA и нет принтеров…


    1. lokkiuni
      14.08.2018 10:53

      Принтер с терминального сервера всё равно использовать.


    1. nitro80
      15.08.2018 01:41

      Vga идеально было бы :( Но среди одноплатников встречается очень редко


      1. nafikovr
        16.08.2018 11:15

        cubieboard вроде имеет на GPIO, cubietruck вообще onboard. про остальные не скажу ничего


    1. JerleShannara
      15.08.2018 03:02

      VGA можно сделать из HDMI, цена вопроса 500-2000р на радиорынке/компьютерном магазине.


      1. nitro80
        15.08.2018 04:36

        цена переходника 70% от стоимости компьютера — многовато


      1. clawham
        15.08.2018 08:39

        открою вам тайну — за 1000 руб я уже готовый компьютер с сетевухой купить могу который сам может грузиться с tftp в wtware и на этом все и заканчивается — работает все отработано все pgg полный вагон


    1. Stanislavvv
      15.08.2018 14:35

      Не знаю, как у этого, а для raspberry pi точно была нахлобучка с vga (грубо говоря, набор резисторов на пинах).


  1. OnelaW
    14.08.2018 17:00

    Just business, все выше перечисленное в цветной коробочке с магическими названиями крупных производителей доходит от 250 американских рублей.

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


    1. nitro80
      15.08.2018 01:43

      На хабре есть компания, которая создавала такое решение на основе cubieboard. Открытый терминальный клиент.
      Видимо, не зашло у них, раз они не пишут ничего в блоге.


      Я покупал поиграться, хорошая штука, выручил терминал, когда основной компьютер сломался.


      1. OnelaW
        15.08.2018 10:02

        Однако.