Создание тонкого клиента на базе дешевых одноплатных ПК +32


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

Проще всего для этого использовать 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
    /#18989551

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

    • Naves
      /#18989615

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

      • Gryphon88
        /#18989627

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

        • Naves
          /#18989633

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

      • Salavat
        /#18989869

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


        Фото Orange Pi Plus 2E

        image

    • KYuri
      /#18989695 / +1

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

      • ivn86
        /#18994563 / +1

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

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

    • soshnikov
      /#18990733

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

    • Max-812
      /#18993647

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

  2. Naves
    /#18989573

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

  3. EmmGold
    /#18989617

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

    • fzn7
      /#18989763

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

      • sintech
        /#18989823

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

        • fzn7
          /#18989847

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

      • edo1h
        /#18990737

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

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

        • Magister7
          /#18992035

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

          • edo1h
            /#18992119

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

            • Magister7
              /#18992155

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

            • nafikovr
              /#18999143

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

        • dlinyj
          /#18992521

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

          • edo1h
            /#18993571

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

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

            • dlinyj
              /#18996265

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

        • vzhicharra
          /#18992745

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

  4. x893
    /#18989923

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

  5. galadhon
    /#18990853

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

    • Naves
      /#18993181

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

  6. Dioxin
    /#18990867

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

    • lokkiuni
      /#18991435

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

      • Dioxin
        /#18991813

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

        • lokkiuni
          /#18991885

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

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

        • nitro80
          /#18994285

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

    • m0rpheus
      /#18991883

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

      • Gryphon88
        /#18992567

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

        • Solexid
          /#18993099 / +1

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

          • Gryphon88
            /#18993101

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

            • Solexid
              /#18993135

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

              • Gryphon88
                /#18993173 / +2

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

                • nitro80
                  /#18994287

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

                  • lokkiuni
                    /#18995531

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

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

          • Naves
            /#18993125 / +1

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

            • lokkiuni
              /#18993325

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

            • Meklon
              /#18993351

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

              • nafikovr
                /#18999171

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

        • JerleShannara
          /#18994333

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

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

          • dlinyj
            /#18996281

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

            • JerleShannara
              /#18998281

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

          • Gryphon88
            /#18998189

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

            • JerleShannara
              /#18998287

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

            • nafikovr
              /#18999187

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

  7. klim76
    /#18990951

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

    • hokum13
      /#18991293

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

    • dMac
      /#18991371

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

  8. clawham
    /#18991183

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

    • lokkiuni
      /#18991441

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

    • nitro80
      /#18994289

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

      • nafikovr
        /#18999197

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

    • JerleShannara
      /#18994337

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

      • nitro80
        /#18994399

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

      • clawham
        /#18994683

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

    • Stanislavvv
      /#18996251

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

  9. OnelaW
    /#18993119

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

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

    • nitro80
      /#18994291

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


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