we MOVED master
authorRalf Jung <post@ralfj.de>
Sun, 20 Apr 2014 16:43:45 +0000 (18:43 +0200)
committerRalf Jung <post@ralfj.de>
Sun, 20 Apr 2014 16:43:45 +0000 (18:43 +0200)
33 files changed:
.gitignore [deleted file]
AndTuer/AndroidManifest.xml [deleted file]
AndTuer/project.properties [deleted file]
AndTuer/res/layout/door.xml [deleted file]
AndTuer/res/menu/main.xml [deleted file]
AndTuer/res/values/strings.xml [deleted file]
AndTuer/res/xml/preferences.xml [deleted file]
AndTuer/src/de/hacksaar/andtuer/AndroidLogging.java [deleted file]
AndTuer/src/de/hacksaar/andtuer/AsyncTyshell.java [deleted file]
AndTuer/src/de/hacksaar/andtuer/DoorActivity.java [deleted file]
AndTuer/src/de/hacksaar/andtuer/DoorSettings.java [deleted file]
AndTuer/src/de/hacksaar/andtuer/IntegerTextPreference.java [deleted file]
JavaTuer/src/de/hacksaar/javatuer/DummyLogging.java [deleted file]
JavaTuer/src/de/hacksaar/javatuer/InteractiveLogin.java [deleted file]
JavaTuer/src/de/hacksaar/javatuer/SshClient.java [deleted file]
JavaTuer/src/de/hacksaar/javatuer/StderrLogging.java [deleted file]
JavaTuer/src/de/hacksaar/javatuer/TuerLogging.java [deleted file]
JavaTuer/src/de/hacksaar/javatuer/TyshellClient.java [deleted file]
Makefile [deleted file]
README [new file with mode: 0644]
actor.py [deleted file]
addtueruser [deleted file]
libtuer.py [deleted file]
pins.py [deleted file]
spaceapi.py [deleted file]
statemachine.jpg [deleted file]
statemachine.odg [deleted file]
statemachine.py [deleted file]
tryshell [deleted file]
tuerd [deleted file]
tyshell [deleted file]
tysock.py [deleted file]
waker.py [deleted file]

diff --git a/.gitignore b/.gitignore
deleted file mode 100644 (file)
index 3afd512..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-__pycache__
-config.py
diff --git a/AndTuer/AndroidManifest.xml b/AndTuer/AndroidManifest.xml
deleted file mode 100644 (file)
index 8591250..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="de.hacksaar.andtuer" android:versionCode="2" android:versionName="0.2">
-    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17"/>
-    <uses-permission android:name="android.permission.INTERNET"/>
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-    <application android:icon="@drawable/ic_launcher" android:label="@string/app_name">
-        <activity android:name="de.hacksaar.andtuer.DoorActivity" android:label="@string/app_name"
-                  android:configChanges="orientation|keyboardHidden|screenSize">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.LAUNCHER"/>
-            </intent-filter>
-        </activity>
-        <activity android:name="de.hacksaar.andtuer.DoorSettings" android:label="Settings"/>
-    </application>
-</manifest>
diff --git a/AndTuer/project.properties b/AndTuer/project.properties
deleted file mode 100644 (file)
index 2aef174..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# This file is automatically generated by IntelliJ IDEA
-# Project target.
-target=android-14
diff --git a/AndTuer/res/layout/door.xml b/AndTuer/res/layout/door.xml
deleted file mode 100644 (file)
index 8133e92..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
-              android:orientation="vertical" android:layout_height="match_parent">
-
-    <LinearLayout android:layout_height="64sp" android:layout_width="match_parent"
-                  android:orientation="horizontal">
-        <Button android:layout_height="match_parent" android:layout_width="0dip" android:layout_weight="1"
-                android:id="@+id/connect_button" android:text="@string/connect"/>
-        <Button android:layout_height="match_parent" android:layout_width="0dip" android:id="@+id/buzz_button"
-                android:layout_weight="1" android:text="@string/buzz" android:enabled="false"/>
-        <Button android:layout_height="match_parent" android:layout_width="0dip" android:id="@+id/unlock_button"
-                android:layout_weight="1" android:text="@string/unlock_door" android:enabled="false"/>
-        <Button android:layout_height="match_parent" android:layout_width="0dip" android:layout_weight="1"
-                android:id="@+id/disconnect_button" android:text="@string/disconnect" android:enabled="false"/>
-    </LinearLayout>
-    <TextView android:id="@+id/logout" android:layout_height="0dip" android:layout_width="match_parent"
-              android:layout_weight="1"/>
-</LinearLayout>
\ No newline at end of file
diff --git a/AndTuer/res/menu/main.xml b/AndTuer/res/menu/main.xml
deleted file mode 100644 (file)
index 0717476..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/menu_settings" android:icon="@android:drawable/ic_menu_preferences"
-          android:title="@string/preferences" android:showAsAction="always"/>
-</menu>
\ No newline at end of file
diff --git a/AndTuer/res/values/strings.xml b/AndTuer/res/values/strings.xml
deleted file mode 100644 (file)
index b87a4c3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string name="app_name">Hacksaar AndTuer</string>
-    <string name="connect">Connect</string>
-    <string name="disconnect">Disconnect</string>
-    <string name="buzz">Buzz</string>
-    <string name="open_door">Open door</string>
-    <string name="close_door">Close door</string>
-    <string name="unlock_door">Unlock</string>
-    <string name="preferences">Preferences</string>
-</resources>
\ No newline at end of file
diff --git a/AndTuer/res/xml/preferences.xml b/AndTuer/res/xml/preferences.xml
deleted file mode 100644 (file)
index b2037f2..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <PreferenceCategory android:title="Server">
-        <EditTextPreference android:key="pref_server_hostname" android:title="Hostname"
-                            android:defaultValue="192.168.178.222"/>
-        <de.hacksaar.andtuer.IntegerTextPreference android:key="pref_server_port" android:title="Port"
-                                                   android:inputType="number" android:defaultValue="22"/>
-    </PreferenceCategory>
-    <PreferenceCategory android:title="User">
-        <EditTextPreference android:key="pref_user_username" android:title="Username"/>
-        <EditTextPreference android:key="pref_user_keyfile" android:title="Keyfile"
-                            android:defaultValue="/sdcard/.ssh/id_rsa"/>
-    </PreferenceCategory>
-</PreferenceScreen>
\ No newline at end of file
diff --git a/AndTuer/src/de/hacksaar/andtuer/AndroidLogging.java b/AndTuer/src/de/hacksaar/andtuer/AndroidLogging.java
deleted file mode 100644 (file)
index e4d0b19..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package de.hacksaar.andtuer;
-
-import android.util.Log;
-import de.hacksaar.javatuer.TuerLogging;
-
-public class AndroidLogging extends TuerLogging {
-       @Override
-       public void debug(String tag, String msg) {
-               Log.d(tag, msg);
-       }
-
-       @Override
-       public void exception(String tag, Throwable t) {
-               Log.w(tag, t);
-       }
-
-       @Override
-       public void info(String tag, String msg) {
-               Log.i(tag, msg);
-       }
-}
diff --git a/AndTuer/src/de/hacksaar/andtuer/AsyncTyshell.java b/AndTuer/src/de/hacksaar/andtuer/AsyncTyshell.java
deleted file mode 100644 (file)
index 6236988..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-package de.hacksaar.andtuer;
-
-import android.os.AsyncTask;
-import android.util.Log;
-import de.hacksaar.javatuer.InteractiveLogin;
-import de.hacksaar.javatuer.TyshellClient;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.LinkedList;
-import java.util.Queue;
-
-class AsyncTyshell extends AsyncTask<Void, Void, Void> {
-
-       private static final String TAG = "AsyncTyshell";
-       private final String hostname;
-       private final int port;
-       private final String username;
-       private final String keyFile;
-       private final Prompter prompter;
-       private final Queue<String> messages = new LinkedList<>();
-       private final Object promptWait = new Object();
-       private String promptResultString;
-       private boolean promptResultBoolean;
-       private boolean disconnect = true;
-
-       AsyncTyshell(String hostname, int port, String username, String keyFile, Prompter prompter) {
-               this.hostname = hostname;
-               this.port = port;
-               this.username = username;
-               this.keyFile = keyFile;
-               this.prompter = prompter;
-       }
-
-       private void awaitPrompt() {
-               synchronized (promptWait) {
-                       try {
-                               promptWait.wait();
-                       } catch (InterruptedException e) {
-                               Log.w(TAG, e);
-                       }
-               }
-       }
-
-       public void disconnect() {
-               disconnect = false;
-               synchronized (promptWait) {
-                       promptWait.notify();
-               }
-               synchronized (messages) {
-                       messages.notify();
-               }
-       }
-
-       private void readUnlimited(InputStreamReader inputStreamReader) {
-               final BufferedReader reader = new BufferedReader(inputStreamReader);
-               new Thread(new Runnable() {
-                       @Override
-                       public void run() {
-                               String line;
-                               try {
-                                       while((line = reader.readLine()) != null) {
-                                               prompter.sendMessage(line);
-                                       }
-                               } catch (Exception e) {
-                                       Log.w("end read unlimited!", e);
-                               }
-                       }
-               }).start();
-       }
-
-       @Override
-       protected Void doInBackground(Void... voids) {
-               TyshellClient client = new TyshellClient(hostname, port, new AndroidLogging());
-               client.connect(username, keyFile, new AsyncInteractiveLogin());
-               readUnlimited(client.getInputStream());
-               while (disconnect) {
-                       String msg = null;
-                       synchronized (messages) {
-                               while (disconnect && (msg = messages.poll()) == null) {
-                                       try {
-                                               messages.wait();
-                                       } catch (InterruptedException e) {
-                                               return null;
-                                       }
-                               }
-                       }
-                       if (msg == null) {
-                               break;
-                       }
-                       client.sendCommand(msg);
-               }
-               client.disconnect();
-               return null;
-       }
-
-       public void promptResult(boolean result) {
-               promptResultBoolean = result;
-               synchronized (promptWait) {
-                       promptWait.notify();
-               }
-       }
-
-       public void promptResult(String result) {
-               promptResultString = result;
-               synchronized (promptWait) {
-                       promptWait.notify();
-               }
-       }
-
-       public void sendCommand(String string) {
-               synchronized (messages) {
-                       messages.add(string);
-                       messages.notify();
-               }
-       }
-
-       public interface Prompter {
-               void promptBoolean(String message);
-
-               void promptString(String message);
-
-               void sendMessage(String message);
-       }
-
-       private class AsyncInteractiveLogin extends InteractiveLogin {
-
-               AsyncInteractiveLogin() {
-               }
-
-               @Override
-               public String promptKeyPassphrase(String question) {
-                       prompter.promptString(question);
-                       awaitPrompt();
-                       return promptResultString;
-               }
-
-               @Override
-               public String promptUserPassword(String question) {
-                       prompter.promptString(question);
-                       awaitPrompt();
-                       return promptResultString;
-               }
-
-               @Override
-               public boolean promptYesNo(String question) {
-                       prompter.promptBoolean(question);
-                       awaitPrompt();
-                       return promptResultBoolean;
-               }
-
-               @Override
-               public void showMessage(String s) {
-                       prompter.sendMessage(s);
-               }
-       }
-}
diff --git a/AndTuer/src/de/hacksaar/andtuer/DoorActivity.java b/AndTuer/src/de/hacksaar/andtuer/DoorActivity.java
deleted file mode 100644 (file)
index 20d1d60..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-package de.hacksaar.andtuer;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.text.InputType;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.EditText;
-import android.widget.TextView;
-
-public class DoorActivity extends Activity implements View.OnClickListener {
-
-       private static final String TAG = "DoorActivity";
-       private static final int DIALOG_BOOLEAN = 7;
-       private static final int DIALOG_STRING = 14;
-       private static final int TEXT_ID = 42;
-       private final AsyncTyshell.Prompter prompter = new DialogPrompter();
-       private TextView logText;
-       private AsyncTyshell task;
-       private String pendingMessage;
-
-       private Dialog askBooleanDialog() {
-               AlertDialog.Builder builder = new AlertDialog.Builder(this);
-               builder.setTitle(null);
-               builder.setMessage(pendingMessage);
-
-               builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
-                       @Override
-                       public void onClick(DialogInterface dialog, int whichButton) {
-                               assert task != null;
-                               task.promptResult(true);
-                       }
-               });
-
-               builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
-                       @Override
-                       public void onClick(DialogInterface dialog, int which) {
-                               assert task != null;
-                               task.promptResult(false);
-                       }
-               });
-
-               return builder.create();
-       }
-
-       private Dialog askStringDialog() {
-               AlertDialog.Builder builder = new AlertDialog.Builder(this);
-               builder.setTitle(null);
-               builder.setMessage(pendingMessage);
-
-               final EditText input = new EditText(this);
-               input.setId(TEXT_ID);
-               input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
-               builder.setView(input);
-
-               builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
-                       @Override
-                       public void onClick(DialogInterface dialog, int whichButton) {
-                               assert task != null;
-                               String value = input.getText().toString();
-                               task.promptResult(value);
-                       }
-               });
-
-               builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
-                       @Override
-                       public void onClick(DialogInterface dialog, int whichButton) {
-                               assert task != null;
-                               task.promptResult(null);
-                       }
-               });
-
-               return builder.create();
-       }
-
-       private void onBuzzClick() {
-               if (task != null) {
-                       task.sendCommand("buzz");
-               }
-       }
-
-       @Override
-       public void onClick(View view) {
-               switch (view.getId()) {
-                       case R.id.connect_button:
-                               onConnectClick();
-                               break;
-                       case R.id.buzz_button:
-                               onBuzzClick();
-                               break;
-                       case R.id.unlock_button:
-                               onUnlockClick();
-                               break;
-                       case R.id.disconnect_button:
-                               onDisconnectClick();
-                               break;
-               }
-       }
-
-       private void onCloseClick() {
-               if (task != null) {
-                       task.sendCommand("close");
-               }
-       }
-
-       private void onConnectClick() {
-               SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
-               task = new AsyncTyshell(preferences.getString(DoorSettings.PREF_SERVER_HOSTNAME, DoorSettings.DEFAULT_HOST),
-                                                               preferences.getInt(DoorSettings.PREF_SERVER_PORT, DoorSettings.DEFAULT_PORT),
-                                                               preferences.getString(DoorSettings.PREF_USER_USERNAME, null),
-                                                               preferences.getString(DoorSettings.PREF_USER_KEYFILE, DoorSettings.DEFAULT_KEYFILE),
-                                                               prompter);
-               task.execute();
-               findViewById(R.id.connect_button).setEnabled(false);
-       }
-
-       @Override
-       public void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-               setContentView(R.layout.door);
-               for (int view : new int[]{R.id.unlock_button, R.id.buzz_button, R.id.disconnect_button, R.id.connect_button}) {
-                       findViewById(view).setOnClickListener(this);
-               }
-               logText = (TextView) findViewById(R.id.logout);
-               try {
-                       logText.setText("Welcome to Hacksaar AndTuer, Version " +
-                                                       getPackageManager().getPackageInfo(getPackageName(), 0).versionName);
-               } catch (Exception e) {
-                       logText.setText("Welcome to Hacksaar AndTuer, [unknown version]");
-               }
-       }
-
-       @Override
-       protected Dialog onCreateDialog(int id) {
-               switch (id) {
-                       case DIALOG_BOOLEAN:
-                               return askBooleanDialog();
-                       case DIALOG_STRING:
-                               return askStringDialog();
-                       default:
-                               return super.onCreateDialog(id);
-               }
-       }
-
-       @Override
-       public boolean onCreateOptionsMenu(Menu menu) {
-               getMenuInflater().inflate(R.menu.main, menu);
-               return super.onCreateOptionsMenu(menu);
-       }
-
-       private void onDisconnectClick() {
-               if (task != null) {
-                       task.sendCommand("exit");
-                       task.disconnect();
-               }
-               findViewById(R.id.unlock_button).setEnabled(false);
-               findViewById(R.id.buzz_button).setEnabled(false);
-               findViewById(R.id.disconnect_button).setEnabled(false);
-               findViewById(R.id.connect_button).setEnabled(true);
-       }
-
-       @Override
-       public boolean onMenuItemSelected(int featureId, MenuItem item) {
-               switch (item.getItemId()) {
-                       case R.id.menu_settings:
-                               startActivity(new Intent(this, DoorSettings.class));
-                               return true;
-                       default:
-                               return super.onMenuItemSelected(featureId, item);
-               }
-       }
-
-       @Override
-       protected void onPrepareDialog(int id, Dialog dialog) {
-               switch (id) {
-                       case DIALOG_STRING:
-                               ((TextView) dialog.findViewById(TEXT_ID)).setText("");
-                       case DIALOG_BOOLEAN:
-                               ((AlertDialog) dialog).setMessage(pendingMessage);
-                               break;
-                       default:
-                               super.onPrepareDialog(id, dialog);
-               }
-
-       }
-
-       private void onUnlockClick() {
-               if (task != null) {
-                       task.sendCommand("unlock");
-               }
-       }
-
-       private void writeLog(String msg) {
-               Log.d(TAG, "Log: " + msg);
-               logText.setText(logText.getText() + "\n" + msg);
-
-               findViewById(R.id.unlock_button).setEnabled(true);
-               findViewById(R.id.buzz_button).setEnabled(true);
-               findViewById(R.id.disconnect_button).setEnabled(true);
-       }
-
-       private class DialogPrompter implements AsyncTyshell.Prompter {
-               DialogPrompter() {
-               }
-
-               @Override
-               public void promptBoolean(String message) {
-                       pendingMessage = message;
-                       runOnUiThread(new Runnable() {
-                               @Override
-                               public void run() {
-                                       showDialog(DIALOG_BOOLEAN);
-                               }
-                       });
-               }
-
-               @Override
-               public void promptString(String message) {
-                       pendingMessage = message;
-                       runOnUiThread(new Runnable() {
-                               @Override
-                               public void run() {
-                                       showDialog(DIALOG_STRING);
-                               }
-                       });
-               }
-
-               @Override
-               public void sendMessage(final String message) {
-                       runOnUiThread(new Runnable() {
-                               @Override
-                               public void run() {
-                                       writeLog(message);
-                               }
-                       });
-               }
-       }
-}
\ No newline at end of file
diff --git a/AndTuer/src/de/hacksaar/andtuer/DoorSettings.java b/AndTuer/src/de/hacksaar/andtuer/DoorSettings.java
deleted file mode 100644 (file)
index 1fd0d7a..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-package de.hacksaar.andtuer;
-
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.Environment;
-import android.preference.Preference;
-import android.preference.PreferenceActivity;
-
-public class DoorSettings extends PreferenceActivity implements Preference.OnPreferenceChangeListener {
-       public static final int DEFAULT_PORT = 22;
-       public static final String DEFAULT_HOST = "192.168.178.222";
-       public static final String DEFAULT_KEYFILE = Environment.getExternalStorageDirectory().getPath() + "/.ssh/id_rsa";
-       private static final String UNSET = "<unset>";
-       public static final String PREF_SERVER_PORT = "pref_server_port";
-       public static final String PREF_USER_USERNAME = "pref_user_username";
-       public static final String PREF_USER_KEYFILE = "pref_user_keyfile";
-       public static final String PREF_SERVER_HOSTNAME = "pref_server_hostname";
-
-       @Override
-       public void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-               addPreferencesFromResource(R.xml.preferences);
-               Preference hostnamePreference = findPreference(PREF_SERVER_HOSTNAME);
-               hostnamePreference.setOnPreferenceChangeListener(this);
-               SharedPreferences sharedPreferences = getPreferenceManager().getSharedPreferences();
-               hostnamePreference.setSummary(sharedPreferences.getString(PREF_SERVER_HOSTNAME, DEFAULT_HOST));
-               Preference portPreference = findPreference(PREF_SERVER_PORT);
-               portPreference.setOnPreferenceChangeListener(this);
-               portPreference.setSummary(Integer.toString(sharedPreferences.getInt(PREF_SERVER_PORT, DEFAULT_PORT)));
-               Preference usernamePreference = findPreference(PREF_USER_USERNAME);
-               usernamePreference.setOnPreferenceChangeListener(this);
-               usernamePreference.setSummary(sharedPreferences.getString(PREF_USER_USERNAME, UNSET));
-               Preference keyfilePreference = findPreference(PREF_USER_KEYFILE);
-               keyfilePreference.setOnPreferenceChangeListener(this);
-               keyfilePreference.setSummary(sharedPreferences.getString(PREF_USER_KEYFILE, DEFAULT_KEYFILE));
-       }
-
-       @Override
-       public boolean onPreferenceChange(Preference preference, Object o) {
-               SharedPreferences sharedPreferences = getPreferenceManager().getSharedPreferences();
-               if (preference.getKey().equals(PREF_SERVER_PORT)) {
-                       preference.setSummary(
-                                       Integer.toString(sharedPreferences.getInt(preference.getKey(), DEFAULT_PORT)));
-               } else {
-                       preference.setSummary(sharedPreferences.getString(preference.getKey(), UNSET));
-               }
-               return true;
-       }
-}
\ No newline at end of file
diff --git a/AndTuer/src/de/hacksaar/andtuer/IntegerTextPreference.java b/AndTuer/src/de/hacksaar/andtuer/IntegerTextPreference.java
deleted file mode 100644 (file)
index 69b750c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-package de.hacksaar.andtuer;
-
-import android.content.Context;
-import android.preference.EditTextPreference;
-import android.util.AttributeSet;
-
-public class IntegerTextPreference extends EditTextPreference {
-       public IntegerTextPreference(Context context, AttributeSet attrs, int defStyle) {
-               super(context, attrs, defStyle);
-       }
-
-       public IntegerTextPreference(Context context, AttributeSet attrs) {
-               super(context, attrs);
-       }
-
-       public IntegerTextPreference(Context context) {
-               super(context);
-       }
-
-       @Override
-       protected String getPersistedString(String defaultReturnValue) {
-               return String.valueOf(getPersistedInt(-1));
-       }
-
-       @Override
-       protected boolean persistString(String value) {
-               return persistInt(Integer.valueOf(value));
-       }
-}
diff --git a/JavaTuer/src/de/hacksaar/javatuer/DummyLogging.java b/JavaTuer/src/de/hacksaar/javatuer/DummyLogging.java
deleted file mode 100644 (file)
index ab37f5b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package de.hacksaar.javatuer;
-
-public class DummyLogging extends TuerLogging {
-       @Override
-       public void debug(String tag, String msg) {
-               // do nothing
-       }
-
-       @Override
-       public void exception(String tag, Throwable t) {
-               // do nothing
-       }
-
-       @Override
-       public void info(String tag, String msg) {
-               // do nothing
-       }
-}
diff --git a/JavaTuer/src/de/hacksaar/javatuer/InteractiveLogin.java b/JavaTuer/src/de/hacksaar/javatuer/InteractiveLogin.java
deleted file mode 100644 (file)
index 29c0c38..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package de.hacksaar.javatuer;
-
-import com.jcraft.jsch.UserInfo;
-
-public abstract class InteractiveLogin implements UserInfo {
-       private String password;
-       private String passphrase;
-
-       @Override
-       public String getPassphrase() {
-               return passphrase;
-       }
-
-       @Override
-       public String getPassword() {
-               return password;
-       }
-
-       public abstract String promptKeyPassphrase(String question);
-
-       @Override
-       public boolean promptPassphrase(String s) {
-               passphrase = promptKeyPassphrase(s);
-               return passphrase != null;
-       }
-
-       @Override
-       public boolean promptPassword(String s) {
-               password = promptUserPassword(s);
-               return password != null;
-       }
-
-       public abstract String promptUserPassword(String question);
-}
diff --git a/JavaTuer/src/de/hacksaar/javatuer/SshClient.java b/JavaTuer/src/de/hacksaar/javatuer/SshClient.java
deleted file mode 100644 (file)
index 7e63d31..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-package de.hacksaar.javatuer;
-
-import com.jcraft.jsch.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class SshClient {
-       private static final String TAG = "SshClient";
-       private final String host;
-       private final String username;
-       private final int port;
-       private final JSch jSch;
-       private final TuerLogging log;
-       private Session session;
-       private Channel channel;
-
-       public SshClient(String host, String username, int port, TuerLogging log) {
-               this.host = host;
-               this.username = username;
-               this.port = port;
-               this.log = log;
-               JSch.setLogger(log);
-               jSch = new JSch();
-       }
-
-       public void addPrivateKey(String keyFilePath) throws JSchException {
-               jSch.addIdentity(keyFilePath);
-       }
-
-       public void addPrivateKey(String keyFilePath, String passphrase) throws JSchException {
-               jSch.addIdentity(keyFilePath, passphrase);
-       }
-
-       public void disconnect() {
-               channel.disconnect();
-               channel = null;
-               session.disconnect();
-               session = null;
-       }
-
-       public String getHost() {
-               return host;
-       }
-
-       public InputStream getInputStream() throws IOException {
-               if (channel == null) {
-                       return null;
-               }
-               return channel.getInputStream();
-       }
-
-       public OutputStream getOutputStream() throws IOException {
-               if (channel == null) {
-                       return null;
-               }
-               return channel.getOutputStream();
-       }
-
-       public int getPort() {
-               return port;
-       }
-
-       public String getUsername() {
-               return username;
-       }
-
-       public boolean isConnected() {
-               return channel != null && channel.isConnected() && session != null && session.isConnected();
-       }
-
-       public void login(final String password) throws JSchException {
-               login(new UserInfo() {
-
-                       @Override
-                       public String getPassphrase() {
-                               return null;
-                       }
-
-                       @Override
-                       public String getPassword() {
-                               return password;
-                       }
-
-                       @Override
-                       public boolean promptPassphrase(String s) {
-                               return false;
-                       }
-
-                       @Override
-                       public boolean promptPassword(String s) {
-                               return true;
-                       }
-
-                       @Override
-                       public boolean promptYesNo(String s) {
-                               return false;
-                       }
-
-                       @Override
-                       public void showMessage(String s) {
-                               log.info(TAG, s);
-                       }
-               });
-       }
-
-       public void login() throws JSchException {
-               login(new UserInfo() {
-
-                       @Override
-                       public String getPassphrase() {
-                               return null;
-                       }
-
-                       @Override
-                       public String getPassword() {
-                               return null;
-                       }
-
-                       @Override
-                       public boolean promptPassphrase(String s) {
-                               return false;
-                       }
-
-                       @Override
-                       public boolean promptPassword(String s) {
-                               return false;
-                       }
-
-                       @Override
-                       public boolean promptYesNo(String s) {
-                               return false;
-                       }
-
-                       @Override
-                       public void showMessage(String s) {
-                               log.info(TAG, s);
-                       }
-               });
-       }
-
-       public void login(UserInfo userInfo) throws JSchException {
-               log.debug(TAG, "Creating session");
-               if (session == null) {
-                       session = jSch.getSession(username, host, port);
-               }
-               if (!session.isConnected()) {
-                       session.setUserInfo(userInfo);
-                       log.debug(TAG, "Connecting");
-                       session.connect();
-                       log.debug(TAG, "Opening channel");
-                       channel = session.openChannel("shell");
-                       channel.connect();
-               }
-       }
-
-}
diff --git a/JavaTuer/src/de/hacksaar/javatuer/StderrLogging.java b/JavaTuer/src/de/hacksaar/javatuer/StderrLogging.java
deleted file mode 100644 (file)
index 326f37d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.hacksaar.javatuer;
-
-public class StderrLogging extends TuerLogging {
-
-       @Override
-       public void debug(String tag, String msg) {
-               System.err.println("D/" + tag + ": " + msg);
-       }
-
-       @Override
-       public void exception(String tag, Throwable t) {
-               System.err.println("E/" + tag + ": " + t.getMessage());
-               t.printStackTrace(System.err);
-       }
-
-       @Override
-       public void info(String tag, String msg) {
-               System.err.println("I/" + tag + ": " + msg);
-       }
-}
diff --git a/JavaTuer/src/de/hacksaar/javatuer/TuerLogging.java b/JavaTuer/src/de/hacksaar/javatuer/TuerLogging.java
deleted file mode 100644 (file)
index 6dbc199..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-package de.hacksaar.javatuer;
-
-import com.jcraft.jsch.Logger;
-
-public abstract class TuerLogging implements Logger {
-
-       public abstract void debug(String tag, String msg);
-
-       public abstract void exception(String tag, Throwable t);
-
-       public abstract void info(String tag, String msg);
-
-       @Override
-       public boolean isEnabled(int i) {
-               return true;
-       }
-
-       @Override
-       public void log(int i, String s) {
-               if (i == 1) {
-                       info("SshConnection", s);
-               }
-       }
-}
diff --git a/JavaTuer/src/de/hacksaar/javatuer/TyshellClient.java b/JavaTuer/src/de/hacksaar/javatuer/TyshellClient.java
deleted file mode 100644 (file)
index 129a7bd..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-package de.hacksaar.javatuer;
-
-import com.jcraft.jsch.JSchException;
-import com.jcraft.jsch.UserInfo;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-
-public class TyshellClient {
-       private static final String TAG = "TyshellClient";
-       public static final char END_OF_COMMAND = '\n';
-       private final String hostname;
-       private final int port;
-       private final TuerLogging log;
-       private SshClient client;
-       private InputStreamReader inputStream;
-       private OutputStreamWriter outputStream;
-
-       public TyshellClient(String hostname, int port) {
-               this(hostname, port, new DummyLogging());
-       }
-
-       public TyshellClient(String hostname, int port, TuerLogging log) {
-               this.log = log;
-               this.hostname = hostname;
-               this.port = port;
-       }
-
-       public void connect(String username, String password) {
-               try {
-                       client = new SshClient(hostname, username, port, log);
-                       client.login(password);
-                       inputStream = new InputStreamReader(client.getInputStream());
-                       outputStream = new OutputStreamWriter(client.getOutputStream());
-               } catch (JSchException | IOException e) {
-                       log.exception(TAG, e);
-               }
-       }
-
-       public void connect(String username, String keyFile, String passphrase) {
-               try {
-                       client = new SshClient(hostname, username, port, log);
-                       client.addPrivateKey(keyFile, passphrase);
-                       client.login();
-                       inputStream = new InputStreamReader(client.getInputStream());
-                       outputStream = new OutputStreamWriter(client.getOutputStream());
-               } catch (JSchException | IOException e) {
-                       log.exception(TAG, e);
-               }
-       }
-
-       public void connect(String username, String keyFile, UserInfo interactiveLogin) {
-               try {
-                       client = new SshClient(hostname, username, port, log);
-                       client.addPrivateKey(keyFile);
-                       client.login(interactiveLogin);
-                       inputStream = new InputStreamReader(client.getInputStream());
-                       outputStream = new OutputStreamWriter(client.getOutputStream());
-               } catch (JSchException | IOException e) {
-                       log.exception(TAG, e);
-               }
-       }
-
-       public void disconnect() {
-               try {
-                       inputStream.close();
-                       outputStream.close();
-               } catch (IOException e) {
-                       log.exception(TAG, e);
-               }
-               client.disconnect();
-       }
-
-       boolean isConnected() {
-               return (client.isConnected() && inputStream != null && outputStream != null);
-       }
-
-       public InputStreamReader getInputStream() {
-               return inputStream;
-       }
-
-       public void sendCommand(String command) {
-               if (isConnected()) {
-                       try {
-                               assert outputStream != null;
-                               log.debug(TAG, "Sending: " + command);
-                               outputStream.write((command + END_OF_COMMAND).toCharArray());
-                               outputStream.flush();
-                       } catch (IOException e) {
-                               log.exception(TAG, e);
-                       }
-               }
-       }
-}
diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index 1bdb074..0000000
--- a/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-files = *.py tuerd tryshell tyshell
-target = /opt/tuer/
-
-all: install
-.PHONY: install
-
-install:
-       cp -v $(files) $(target)
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..0ce7747
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+This repository was MOVED to <https://git.hacksaar.de/hacksaar/sphinx>.
+Please go there for the current version, and update your remote URLs.
diff --git a/actor.py b/actor.py
deleted file mode 100644 (file)
index fb72df7..0000000
--- a/actor.py
+++ /dev/null
@@ -1,63 +0,0 @@
-from libtuer import ThreadFunction, logger
-import RPi.GPIO as GPIO
-import time
-       
-class Actor:
-       CMD_BUZZ      = 0
-       CMD_UNLOCK    = 1
-       CMD_LOCK      = 2
-       CMD_GREEN_ON  = 3
-       CMD_GREEN_OFF = 4
-       CMD_RED_ON    = 5
-       CMD_RED_OFF   = 6
-       
-       class CMD():
-               def __init__(self, name, pin, tid, todo, verbose = True):
-                       self.name = name
-                       self.pin = pin
-                       self.tid = tid
-                       self.todo = todo
-                       self.verbose = verbose
-                       # don't do the GPIO setup here, the main init did not yet run
-               
-               def execute(self):
-                       if self.verbose:
-                               logger.info("Actor: Running command %s" % self.name)
-                       else:
-                               logger.debug("Actor: Running command %s" % self.name)
-                       for (value, delay) in self.todo:
-                               if value is not None:
-                                       logger.debug("Actor: Setting pin %d to %d" % (self.pin, value))
-                                       GPIO.output(self.pin, value)
-                               if delay > 0:
-                                       time.sleep(delay)
-       
-       CMDs = {
-               CMD_UNLOCK:  CMD("unlock",         pin=12, tid=0, todo=[(True, 0.3), (False, 0.1)]),
-               CMD_LOCK:  CMD("lock",             pin=16, tid=0, todo=[(True, 0.3), (False, 0.1)]),
-               CMD_BUZZ: CMD("buzz",              pin=22, tid=1, todo=[(True, 2.5), (False, 0.1)]),
-               CMD_GREEN_ON: CMD("green on",      pin=23, tid=2, verbose=False, todo=[(True, 0)]),
-               CMD_GREEN_OFF: CMD("green off",    pin=23, tid=2, verbose=False, todo=[(False, 0)]),
-               CMD_RED_ON: CMD("red on",          pin=26, tid=2, verbose=False, todo=[(True, 0)]),
-               CMD_RED_OFF: CMD("red off",        pin=26, tid=2, verbose=False, todo=[(False, 0)]),
-       }
-       
-       def __init__(self):
-               # launch threads, all running the "_execute" method
-               self.threads = {}
-               for cmd in Actor.CMDs.values():
-                       GPIO.setup(cmd.pin, GPIO.OUT)
-                       GPIO.output(cmd.pin, False)
-                       if not cmd.tid in self.threads:
-                               self.threads[cmd.tid] = ThreadFunction(self._execute, "Actor TID %d" % cmd.tid)
-       
-       def _execute(self, cmd):
-               Actor.CMDs[cmd].execute()
-       
-       def act(self, cmd):
-               # dispatch command to correct thread
-               self.threads[Actor.CMDs[cmd].tid](cmd)
-       
-       def stop(self):
-               for thread in self.threads.values():
-                       thread.stop()
diff --git a/addtueruser b/addtueruser
deleted file mode 100755 (executable)
index 19b10ce..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-USER="$1"
-if [[ -z "$USER" ]]; then
-       echo "Usage: $0 username"
-       exit 1
-fi
-if [[ "$(whoami)" != "root" ]]; then
-       echo "Please get root first"
-       exit 1
-fi
-
-adduser "$USER" --disabled-password
-sudo adduser "$USER" tuer
-cd /home/"$USER"
-mkdir .ssh
-echo -n "I will now open nano, please paste the SSH key in there! "
-read
-nano .ssh/authorized_keys
-chown "$USER": -R .
diff --git a/libtuer.py b/libtuer.py
deleted file mode 100644 (file)
index f1e8d54..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-import logging, logging.handlers, os, time, queue, threading, subprocess
-import traceback, smtplib
-import email.mime.text, email.utils
-
-# Logging configuration
-syslogLevel = logging.INFO
-mailLevel   = logging.CRITICAL # must be "larger" than syslog level!
-from config import mailAddress
-printLevel  = logging.DEBUG
-
-# Mail logging handler
-def sendeMail(subject, text, receivers, sender='sphinx@hacksaar.de', replyTo=None):
-       assert isinstance(receivers, list)
-       if not len(receivers): return # nothing to do
-       # construct content
-       msg = email.mime.text.MIMEText(text.encode('UTF-8'), 'plain', 'UTF-8')
-       msg['Subject'] = subject
-       msg['Date'] = email.utils.formatdate(localtime=True)
-       msg['From'] = sender
-       msg['To'] = ', '.join(receivers)
-       if replyTo is not None:
-               msg['Reply-To'] = replyTo
-       # put into envelope and send
-       s = smtplib.SMTP('localhost')
-       s.sendmail(sender, receivers, msg.as_string())
-       s.quit()
-
-# logging function
-class Logger:
-       def __init__ (self):
-               self.syslog = logging.getLogger("tuerd")
-               self.syslog.setLevel(logging.DEBUG)
-               self.syslog.addHandler(logging.handlers.SysLogHandler(address = '/dev/log',
-                                                                                                               facility = logging.handlers.SysLogHandler.LOG_LOCAL0))
-       
-       def _log (self, lvl, what):
-               thestr = "%s[%d]: %s" % ("tuerd", os.getpid(), what)
-               # console log
-               if lvl >= printLevel:
-                       print(thestr)
-               # syslog
-               if lvl >= syslogLevel:
-                       self.syslog.log(lvl, thestr)
-               # mail log
-               if lvl >= mailLevel and mailAddress is not None:
-                       sendeMail('Kritischer Türfehler', what, mailAddress)
-       
-       def debug(self, what):
-               self._log(logging.DEBUG, what)
-       def info(self, what):
-               self._log(logging.INFO, what)
-       def warning(self, what):
-               self._log(logging.WARNING, what)
-       def error(self, what):
-               self._log(logging.ERROR, what)
-       def critical(self, what):
-               self._log(logging.CRITICAL, what)
-
-logger = Logger()
-
-# run a Python command asynchronously
-def fire_and_forget(f):
-       def _fire_and_forget():
-               try:
-                       f()
-               except Exception:
-                       logger.critical("fire_and_forget: Got exception out of callback:\n%s" % traceback.format_exc())
-       t = threading.Thread(target=_fire_and_forget)
-       t.start()
-
-# run a command asynchronously and log the return value if not 0
-# prefix must be a string identifying the code position where the call came from
-def fire_and_forget_cmd (cmd, log_prefix):
-       logger.debug("Firing and forgetting command from %s: %s" % (log_prefix,str(cmd)))
-       def _fire_and_forget_cmd ():
-               with open("/dev/null", "w") as fnull:
-                       retcode = subprocess.call(cmd, stdout=fnull, stderr=fnull)
-                       if retcode is not 0:
-                               logger.error("%sReturn code %d at command: %s" % (log_prefix,retcode,str(cmd)))
-       fire_and_forget(_fire_and_forget_cmd)
-
-# Threaded callback class
-class ThreadFunction():
-       _CALL = 0
-       _TERM = 1
-       
-       def __init__(self, f, name):
-               self.name = name
-               self._f = f
-               self._q = queue.Queue()
-               self._t = threading.Thread(target=self._thread_func)
-               self._t.start()
-       
-       def _thread_func(self):
-               while True:
-                       (cmd, data) = self._q.get()
-                       # run command
-                       if cmd == ThreadFunction._CALL:
-                               try:
-                                       self._f(*data)
-                               except Exception as e:
-                                       logger.critical("ThreadFunction: Got exception out of handler thread %s:\n%s" % (self.name, traceback.format_exc()))
-                       elif cmd == ThreadFunction._TERM:
-                               assert data is None
-                               break
-                       else:
-                               logger.error("ThreadFunction: Command %d does not exist" % cmd)
-       
-       def __call__(self, *arg):
-               self._q.put((ThreadFunction._CALL, arg))
-       
-       def stop(self):
-               # empty the queue
-               try:
-                       while True:
-                               self._q.get_nowait()
-               except queue.Empty:
-                       pass
-               # now wait till the job-in-progress is done
-               self._q.put((ThreadFunction._TERM, None))
-               self._t.join()
-
-# Thread timer-repeater class: Call a function every <sleep_time> seconds
-class ThreadRepeater():
-       def __init__(self, f, sleep_time, name):
-               self.name = name
-               self._f = f
-               self._stop = False
-               self._sleep_time = sleep_time
-               self._t = threading.Thread(target=self._thread_func)
-               self._t.start()
-       
-       def _thread_func(self):
-               while True:
-                       if self._stop:
-                               break
-                       try:
-                               self._f()
-                       except Exception as e:
-                               logger.critical("ThreadRepeater: Got exception out of handler thread %s:\n%s" % (self.name, traceback.format_exc()))
-                       time.sleep(self._sleep_time)
-       
-       def stop(self):
-               self._stop = True
-               self._t.join()
diff --git a/pins.py b/pins.py
deleted file mode 100644 (file)
index 88a17c2..0000000
--- a/pins.py
+++ /dev/null
@@ -1,72 +0,0 @@
-import RPi.GPIO as GPIO
-from collections import namedtuple
-from libtuer import ThreadRepeater, logger
-from statemachine import StateMachine
-
-class PinsState():
-       pass
-
-class PinWatcher():
-       def __init__(self, pin, histlen):
-               GPIO.setup(pin, GPIO.IN)
-               assert histlen > 1 # otherwise our logic goes nuts...
-               self.pin = pin
-               self._histlen = histlen
-               # state change detection
-               self.state = None
-               self._newstate = None # != None iff we are currently seeing a state change
-               self._newstatelen = 0 # only valid if newstate != None
-       
-       def read(self):
-               curstate = GPIO.input(self.pin)
-               assert curstate in (0, 1)
-               if curstate != self.state:
-                       # the state is about to change
-                       if curstate == self._newstate:
-                               # we already saw this new state
-                               self._newstatelen += 1
-                               if self._newstatelen >= self._histlen:
-                                       # we saw it often enough to declare it the new state
-                                       self.state = curstate
-                                       self._newstate = None
-                                       return True
-                       else:
-                               # now check for how long we see this new state
-                               self._newstate = curstate
-                               self._newstatelen = 1
-               else:
-                       # old state is preserved
-                       self._newstate = None
-               return False
-
-class PinsWatcher():
-       def __init__(self, state_machine):
-               self._pins = {
-                       'bell_ringing': PinWatcher(18, 2),
-                       'door_closed': PinWatcher(8, 4),
-                       'door_locked': PinWatcher(10, 4),
-                       'space_active': PinWatcher(24, 4),
-               }
-               self._sm = state_machine
-               
-               # start a thread doing the work
-               self._t = ThreadRepeater(self._read, 0.02, name="PinsWatcher")
-       
-       def _read(self):
-               saw_change = False
-               for name in self._pins.keys():
-                       pin = self._pins[name]
-                       if pin.read():
-                               saw_change = True
-                               logger.debug("Pin %s changed to %d" % (name, pin.state))
-               if not saw_change:
-                       return None
-               # create return object
-               pinsState = PinsState()
-               for name in self._pins.keys():
-                       setattr(pinsState, name, self._pins[name].state)
-               # send it to state machine
-               self._sm.callback(StateMachine.CMD_PINS, pinsState)
-       
-       def stop(self):
-               self._t.stop()
diff --git a/spaceapi.py b/spaceapi.py
deleted file mode 100644 (file)
index 181981a..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-from threading import Lock
-from libtuer import ThreadFunction, logger
-import urllib.request, time
-
-from config import spaceApiKey
-
-RETRY_TIME = 60
-HEARTBEAT_TIME = 10*60
-
-class SpaceApi:
-       def __init__ (self, waker):
-               self._local_state = None
-               self._remote_state = None
-               self._last_set_at = 0
-               self._running = True
-               self._fail_count = 0 # number of consecutive fails
-               self.set_state = ThreadFunction(self._set_state, "Space API")
-               waker.register(self.set_state, RETRY_TIME)
-       
-       def stop (self):
-               self.set_state.stop()
-       
-       def _do_request(self, state):
-               state_val = 1 if state else 0
-               try:
-                       logger.info("Setting SpaceAPI to %d" % state_val)
-                       url = "https://spaceapi.hacksaar.de/status.php?action=update&key=%s&status=%d" % (spaceApiKey, state_val)
-                       response = urllib.request.urlopen(url, timeout=5.0)
-                       responseText = response.read().decode('utf-8').strip()
-                       if response.getcode() == 200 and responseText == "UpdateSuccessful": return True
-                       logger.error("SpaceAPI returned unexpected code %d, content %s" % (response.getcode(), responseText))
-                       return False
-               except urllib.request.URLError as e:
-                       logger.error("SpaceAPI update returned error: %s" % str(e))
-                       return False
-       
-       # set_state is the asynchronous version of _set_state (see __init__)
-       def _set_state (self, state = None):
-               '''Sets the state, if None: leave state unchanged and re-try if previous attempts failed'''
-               if state is not None:
-                       self._local_state = state
-               # check if there's something we need to do: There's a valid state, and either the state has changed or
-               # we need to refresh our heartbeta)
-               now = time.time()
-               if self._local_state is not None and (self._local_state != self._remote_state or now > self._last_set_at+HEARTBEAT_TIME):
-                       # take action!
-                       success = self._do_request(self._local_state)
-                       if success:
-                               self._remote_state = self._local_state
-                               self._last_set_at = now
-                               self._fail_count = 0
-                       else:
-                               self._fail_count += 1
-                               if self._fail_count in (5, 100):
-                                       logger.critical("Updating the SpaceAPI failed %d times in a row" % self._fail_count)
diff --git a/statemachine.jpg b/statemachine.jpg
deleted file mode 100644 (file)
index 4643df3..0000000
Binary files a/statemachine.jpg and /dev/null differ
diff --git a/statemachine.odg b/statemachine.odg
deleted file mode 100644 (file)
index d32026c..0000000
Binary files a/statemachine.odg and /dev/null differ
diff --git a/statemachine.py b/statemachine.py
deleted file mode 100644 (file)
index a5e52f6..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-from libtuer import ThreadFunction, logger, fire_and_forget, fire_and_forget_cmd
-from actor import Actor
-import os, random, time, threading, datetime
-
-# logger.{debug,info,warning,error,critical}
-
-def play_sound (what):
-       try:
-               soundfiles = os.listdir(SOUNDS_DIRECTORY+what)
-       except FileNotFoundError:
-               logger.error("StateMachine: Unable to list sound files in %s" % (SOUNDS_DIRECTORY+what))
-               return
-       soundfile = SOUNDS_DIRECTORY + what + '/' + random.choice(soundfiles)
-       hour = datetime.datetime.time(datetime.datetime.now()).hour
-       volume = 60 if hour >= 22 or hour <= 6 else 90
-       fire_and_forget_cmd ([SOUNDS_PLAYER, "-volume", str(volume), soundfile], "StateMachine: ")
-
-# convert an absolute nervlist to a relative one
-def nervlist_abs2rel(nervlist_abs):
-       nervlist_rel = []
-       last_t = 0
-       for (t, f) in nervlist_abs:
-               assert t >= last_t
-               nervlist_rel.append((t-last_t, f))
-               last_t = t
-       return nervlist_rel
-
-# StateAuf constants
-HELLO_PROBABILITY = 0.2
-
-# StateUnlocking constants
-OPEN_REPEAT_TIMEOUT = 7
-OPEN_REPEAT_NUMBER = 3
-
-# StateLocking constants
-CLOSE_REPEAT_TIMEOUT = 7
-CLOSE_REPEAT_NUMBER = 3
-
-# StateFallback constants
-FALLBACK_LEAVE_DELAY_LOCK = 5 # seconds
-
-# StateAboutToOpen constants
-SWITCH_PRAISE_PROBABILITY = 0.5
-ABOUTOPEN_NERVLIST = nervlist_abs2rel([(10, lambda:play_sound("flipswitch")),\
-       (20, lambda:play_sound("flipswitch")), (30, lambda:play_sound("flipswitch")), (30, lambda:logger.error("Space open but switch not flipped for 30 seconds")),\
-       (40, lambda:play_sound("flipswitch")), (50, lambda:play_sound("flipswitch")), (60, lambda:play_sound("mail_sent")),
-       (60, lambda:logger.critical("Space open but switch not flipped for 60 seconds")), (120, lambda:play_sound("mail_sent")),
-       (10*60, lambda:logger.critical("Space open but switch not flipped for 10 minutes")),
-       (60*60, lambda:logger.critical("Space open but switch not flipped for one hour"))])
-
-# Timeout we wait after the switch was switched to "Closed", until we assume nobody will open the door and we just lock it
-# ALso the time we wait after the door was opend, till we assume something went wrong and start nerving
-LEAVE_TIMEOUT = 20
-
-# play_sound constants
-SOUNDS_DIRECTORY = "/opt/tuer/sounds/"
-SOUNDS_PLAYER = "/usr/bin/mplayer"
-
-
-class Nerver():
-       # A little utility class used to run the nervlists. A nervlist is a list of (n, f) tuples where f() is run after n seconds.
-       # If f returns something, that's also returned by nerv.
-       def __init__(self, nervlist):
-               self.nervlist = list(nervlist)
-               self.last_event_time = time.time()
-       
-       def nerv(self):
-               if len(self.nervlist):
-                       (wait_time, f) = self.nervlist[0]
-                       now = time.time()
-                       time_gone = now-self.last_event_time
-                       # check if the first element is to be triggered
-                       if time_gone >= wait_time:
-                               self.nervlist = self.nervlist[1:] # "pop" the first element, but do not modify original list
-                               self.last_event_time = now
-                               return f()
-
-
-class StateMachine():
-       # commands you can send
-       CMD_PINS = 0
-       CMD_BUZZ = 1
-       CMD_UNLOCK = 2
-       CMD_WAKEUP = 3
-       CMD_LAST = 4
-       CMD_LOCK = 5
-       CMD_FALLBACK_ON = 6
-       CMD_FALLBACK_OFF = 7
-       CMD_STATUS = 8
-       
-       class State():
-               def __init__(self, state_machine, nervlist = None):
-                       self.state_machine = state_machine
-                       self._nerver = None if nervlist is None else Nerver(nervlist)
-               def handle_pins_event(self):
-                       pass # one needn't implement this
-               def handle_buzz_event(self,arg): # this shouldn't be overwritten
-                       # Buzz twice to give users more time to run ;-)
-                       self.actor().act(Actor.CMD_BUZZ)
-                       self.actor().act(Actor.CMD_BUZZ)
-                       arg("200 okay: buzz executed")
-               def handle_cmd_unlock_event(self,arg):
-                       if arg is not None:
-                               arg("412 Precondition Failed: The current state (%s) cannot handle the UNLOCK command. Try again later." % self.__class__.__name__)
-               def handle_wakeup_event(self):
-                       if self._nerver is not None:
-                               return self._nerver.nerv()
-               def handle_cmd_lock_event(self,arg):
-                       arg("412 Precondition Failed: If not in fallback mode, use the hardware switch to lock the space.")
-               def handle_cmd_fallback_on_event(self,arg):
-                       arg("200 okay: Entering fallback mode and notifying admins.")
-                       logger.critical("Entering fallback mode. Somebody thinks, the hardware sensors are broken.")
-                       return StateMachine.StateFallback(self.state_machine)
-               def handle_cmd_fallback_off_event(self,arg):
-                       arg("412 Precondition Failed: Not in fallback mode!")
-               def handle_cmd_status_event(self,arg):
-                       # TODO use a proper JSON lib
-                       arg('200 okay: {state:\"%s\"}' % self.__class__.__name__)
-               def on_leave(self):
-                       pass
-               def pins(self):
-                       return self.state_machine.pins
-               def old_pins(self):
-                       return self.state_machine.old_pins
-               def actor(self):
-                       return self.state_machine.actor
-               def api(self):
-                       return self.state_machine.api
-               def handle_event(self,ev,arg): # don't override
-                       if ev == StateMachine.CMD_PINS:
-                               return self.handle_pins_event()
-                       elif ev == StateMachine.CMD_BUZZ:
-                               return self.handle_buzz_event(arg)
-                       elif ev == StateMachine.CMD_UNLOCK:
-                               return self.handle_cmd_unlock_event(arg)
-                       elif ev == StateMachine.CMD_WAKEUP:
-                               return self.handle_wakeup_event()
-                       elif ev == StateMachine.CMD_LOCK:
-                               return self.handle_cmd_lock_event(arg)
-                       elif ev == StateMachine.CMD_FALLBACK_ON:
-                               return self.handle_cmd_fallback_on_event(arg)
-                       elif ev == StateMachine.CMD_FALLBACK_OFF:
-                               return self.handle_cmd_fallback_off_event(arg)
-                       elif ev == StateMachine.CMD_STATUS:
-                               return self.handle_cmd_status_event(arg)
-                       else:
-                               raise Exception("Unknown command number: %d" % ev)
-       
-       class AbstractNonStartState(State):
-               def handle_pins_event(self):
-                       if self.pins().door_locked != (not self.pins().space_active):
-                               self.actor().act(Actor.CMD_RED_ON)
-                       else:
-                               self.actor().act(Actor.CMD_RED_OFF)
-                       return super().handle_pins_event()
-       
-       class AbstractLockedState(AbstractNonStartState):
-               '''A state with invariant "The space is locked", switching to StateAboutToOpen when the space becomes unlocked'''
-               def __init__(self, sm, nervlist = None):
-                       super().__init__(sm, nervlist)
-                       self.actor().act(Actor.CMD_GREEN_OFF)
-               def handle_pins_event(self):
-                       if not self.pins().door_locked:
-                               logger.info("Door unlocked, space is about to open")
-                               return StateMachine.StateAboutToOpen(self.state_machine)
-                       return super().handle_pins_event()
-       
-       class AbstractUnlockedState(AbstractNonStartState):
-               '''A state with invariant "The space is unlocked", switching to StateZu when the space becomes locked'''
-               def __init__(self, sm, nervlist = None):
-                       super().__init__(sm, nervlist)
-                       self.actor().act(Actor.CMD_GREEN_ON)
-               def handle_pins_event(self):
-                       if self.pins().door_locked:
-                               logger.info("Door locked, closing space")
-                               if self.pins().space_active:
-                                       logger.warning("StateMachine: door manually locked, but space switch is still on - going to StateZu")
-                                       play_sound("manual_lock")
-                               return StateMachine.StateZu(self.state_machine)
-                       return super().handle_pins_event()
-       
-       class StateStart(State):
-               def __init__(self, sm, nervlist = None, fallback=False):
-                       super().__init__(sm, nervlist)
-                       self.fallback = fallback
-               def handle_pins_event(self):
-                       pins = self.pins()
-                       if not (pins.door_locked is None or pins.door_closed is None or pins.space_active is None or pins.bell_ringing is None):
-                               if self.fallback:
-                                       logger.info("Going to StateFallback because running in fallback mode")
-                                       return StateMachine.StateFallback(self.state_machine)
-                               if pins.door_locked:
-                                       logger.info("All sensors got a value, switching to a proper state: Space is closed")
-                                       return StateMachine.StateZu(self.state_machine)
-                               else:
-                                       logger.info("All sensors got a value, switching to a proper state: Space is (about to) open")
-                                       return StateMachine.StateAboutToOpen(self.state_machine)
-                       return super().handle_pins_event()
-       
-       class StateFallback(State):
-               def __init__(self, sm, nervlist = None):
-                       super().__init__(sm, nervlist)
-                       self._red_state = False
-               def handle_pins_event(self):
-                       pins = self.pins()
-                       # set green LED according to space switch
-                       if pins.space_active:
-                               self.actor().act(Actor.CMD_GREEN_ON)
-                       else:
-                               self.actor().act(Actor.CMD_GREEN_OFF)
-                       # primitive leaving procedure if space switch turned off
-                       if not pins.space_active and self.old_pins().space_active:
-                               def _close_after_time():
-                                       time.sleep(FALLBACK_LEAVE_DELAY_LOCK)
-                                       self.actor().act(Actor.CMD_LOCK)
-                               fire_and_forget(_close_after_time)
-                       # not calling superclass because we want to stay in fallback mode
-               def handle_wakeup_event(self):
-                       # blink red LED
-                       if self._red_state:
-                               self.actor().act(Actor.CMD_RED_OFF)
-                               self._red_state = False
-                       else:
-                               self.actor().act(Actor.CMD_RED_ON)
-                               self._red_state = True
-               def handle_cmd_unlock_event(self,arg):
-                       if arg is not None:
-                               arg("200 okay: Trying to unlock the door. The System is in fallback mode, success information is not available.")
-                       self.actor().act(Actor.CMD_UNLOCK)
-               def handle_cmd_lock_event(self,arg):
-                       if arg is not None:
-                               arg("200 okay: Trying to lock the door. The System is in fallback mode, success information is not available.")
-                       self.actor().act(Actor.CMD_LOCK)
-               def handle_cmd_fallback_on_event(self,arg):
-                       arg("412 Precondition Failed: Fallback mode already active.")
-               def handle_cmd_fallback_off_event(self,arg):
-                       arg("200 okay: Leaving fallback mode and notifying admins.")
-                       logger.critical("Leaving fallback mode. Somebody thinks, the sensors are working again.")
-                       return StateMachine.StateStart(self.state_machine)
-       
-       class StateZu(AbstractLockedState):
-               def handle_cmd_unlock_event(self,callback):
-                       return StateMachine.StateUnlocking(self.state_machine, callback)
-               def handle_pins_event(self):
-                       if not self.old_pins().space_active and self.pins().space_active: # first thing to check: edge detection
-                               logger.info("Space toggled to active while it was closed - unlocking the door")
-                               return StateMachine.StateUnlocking(self.state_machine)
-                       return super().handle_pins_event()
-       
-       class StateUnlocking(AbstractLockedState):
-               def __init__(self,sm,callback=None):
-                       # construct a nervlist
-                       nervlist = [(OPEN_REPEAT_TIMEOUT, lambda: self.actor().act(Actor.CMD_UNLOCK)) for t in range(OPEN_REPEAT_NUMBER)]
-                       nervlist += [(OPEN_REPEAT_TIMEOUT, self.could_not_open)]
-                       super().__init__(sm,nervlist)
-                       self.callbacks = []
-                       self.actor().act(Actor.CMD_UNLOCK)
-                       # enqueue the callback
-                       self.handle_cmd_unlock_event(callback)
-               def notify(self, s, lastMsg):
-                       for cb in self.callbacks:
-                               cb(s, lastMsg)
-               def on_leave(self):
-                       s = "200 okay: door unlocked" if not self.pins().door_locked else ("500 internal server error: Couldn't unlock door with %d tries Ã  %f seconds" % (OPEN_REPEAT_NUMBER,OPEN_REPEAT_TIMEOUT))
-                       self.notify(s, lastMsg=True)
-               def handle_cmd_unlock_event(self,callback):
-                       if callback is not None:
-                               callback("202 processing: Trying to unlock the door", lastMsg=False)
-                               self.callbacks.append(callback)
-               def could_not_open(self):
-                       logger.critical("StateMachine: Couldn't open door after %d tries. Going back to StateZu." % OPEN_REPEAT_NUMBER)
-                       return StateMachine.StateZu(self.state_machine)
-       
-       class AbstractStateWhereUnlockingIsRedundant(AbstractUnlockedState):
-               def handle_cmd_unlock_event(self, callback):
-                       callback("299 redundant: Space seems to be already open. Still processing your request tough.")
-                       logger.info("StateMachine: Received UNLOCK command in %s. This should not be necessary." % self.__class__.__name__)
-                       self.actor().act(Actor.CMD_UNLOCK)
-       
-       class StateAboutToOpen(AbstractStateWhereUnlockingIsRedundant):
-               def __init__(self, sm):
-                       super().__init__(sm, ABOUTOPEN_NERVLIST)
-               def handle_pins_event(self):
-                       pins = self.pins()
-                       if pins.space_active:
-                               logger.info("Space activated, opening procedure completed")
-                               if not self.old_pins().space_active and random.random() <= SWITCH_PRAISE_PROBABILITY:
-                                       play_sound("success")
-                               return StateMachine.StateAuf(self.state_machine)
-                       return super().handle_pins_event()
-       
-       class StateAuf(AbstractStateWhereUnlockingIsRedundant):
-               def __init__(self,sm):
-                       nervlist = [(24*60*60, lambda: logger.critical("Space is now open for 24h. Is everything all right?"))]
-                       super().__init__(sm, nervlist)
-                       self.last_buzzed = None
-                       self.api().set_state(True)
-               def handle_pins_event(self):
-                       pins = self.pins()
-                       if pins.bell_ringing and not self.old_pins().bell_ringing: # first thing to check: edge detection
-                               # someone just pressed the bell
-                               logger.info("StateMachine: buzzing because of bell ringing in StateAuf")
-                               self.actor().act(Actor.CMD_BUZZ)
-                       if not pins.space_active:
-                               logger.info("StateMachine: space switch turned off - starting leaving procedure")
-                               return StateMachine.StateAboutToLeave(self.state_machine)
-                       if not pins.door_closed and self.old_pins().door_closed and random.random() <= HELLO_PROBABILITY:
-                               play_sound("hello")
-                       return super().handle_pins_event()
-               def on_leave(self):
-                       self.api().set_state(False)
-       
-       class StateLocking(AbstractUnlockedState):
-               def __init__(self,sm):
-                       # construct a nervlist
-                       nervlist = [(CLOSE_REPEAT_TIMEOUT, lambda: self.actor().act(Actor.CMD_LOCK)) for t in range(CLOSE_REPEAT_NUMBER)]
-                       nervlist += [(CLOSE_REPEAT_TIMEOUT, self.could_not_close)]
-                       super().__init__(sm, nervlist)
-                       if self.pins().door_closed: # this should always be true, but just to be sure...
-                               self.actor().act(Actor.CMD_LOCK)
-               def handle_pins_event(self):
-                       pins = self.pins()
-                       if not pins.door_closed:
-                               # TODO play a sound? This shouldn't happen, door was opened while we are locking
-                               logger.warning("StateMachine: door manually opened during locking")
-                               return StateMachine.StateAboutToOpen(self.state_machine)
-                       # TODO do anything here if the switch is activated now?
-                       return super().handle_pins_event()
-               def handle_cmd_unlock_event(self,callback):
-                       callback("409 conflict: The sphinx is currently trying to lock the door. Try again later.")
-               def could_not_close(self):
-                       logger.critical("StateMachine: Couldn't close door after %d tries. Going back to StateAboutToOpen." % CLOSE_REPEAT_NUMBER)
-                       return StateMachine.StateAboutToOpen(self.state_machine)
-       
-       class StateAboutToLeave(AbstractUnlockedState):
-               def __init__(self, sm):
-                       nervlist = [(LEAVE_TIMEOUT, lambda: StateMachine.StateLocking(self.state_machine))]
-                       super().__init__(sm, nervlist)
-               def handle_pins_event(self):
-                       if not self.pins().door_closed:
-                               return StateMachine.StateLeaving(self.state_machine)
-                       if self.pins().space_active:
-                               logger.info("Space re-activated, cancelling leaving procedure")
-                               return StateMachine.StateAuf(self.state_machine)
-                       return super().handle_pins_event()
-       
-       class StateLeaving(AbstractUnlockedState):
-               def __init__(self, sm):
-                       nervlist = [(LEAVE_TIMEOUT, lambda: StateMachine.StateAboutToOpen(self.state_machine))]
-                       super().__init__(sm, nervlist)
-               def handle_pins_event(self):
-                       if self.pins().door_closed:
-                               logger.info("The space was left, locking the door")
-                               return StateMachine.StateLocking(self.state_machine)
-                       if self.pins().space_active:
-                               logger.info("Space re-activated, cancelling leaving procedure")
-                               return StateMachine.StateAuf(self.state_machine)
-                       return super().handle_pins_event()
-       
-       def __init__(self, actor, waker, api, fallback = False):
-               self.actor = actor
-               self.api = api
-               self.callback = ThreadFunction(self._callback, name="StateMachine")
-               self.current_state = StateMachine.StateStart(self, fallback=fallback)
-               self.pins = None
-               self.old_pins = None
-               waker.register(lambda: self.callback(StateMachine.CMD_WAKEUP), 1.0) # wake up every second
-               # initially, the space is closed
-               api.set_state(False)
-       
-       def stop (self):
-               self.callback.stop()
-       
-       # actually call this.callback (is set in the constructor to make this thread safe)
-       def _callback(self, cmd, arg=None):
-               # update pins
-               if cmd == StateMachine.CMD_PINS:
-                       self.pins = arg
-               # handle stuff
-               newstate = self.current_state.handle_event(cmd,arg) # returns None or an instance of the new state
-               self.old_pins = self.pins
-               while newstate is not None:
-                       assert isinstance(newstate, StateMachine.State), "I should get a state"
-                       self.current_state.on_leave()
-                       logger.info("StateMachine: Doing state transition %s -> %s" % (self.current_state.__class__.__name__, newstate.__class__.__name__))
-                       self.current_state = newstate
-                       newstate = self.current_state.handle_event(StateMachine.CMD_PINS, self.pins)
diff --git a/tryshell b/tryshell
deleted file mode 100755 (executable)
index 1880dd5..0000000
--- a/tryshell
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python3
-
-import readline
-import socket
-
-tuerSock = "/run/tuer.sock"
-
-while True:
-       command = input("# ") # EOFError used to exit
-       s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-       s.connect(tuerSock)
-       s.send(command.encode())
-       while True:
-               data = s.recv(256)
-               if not len(data): break
-               print(data)
-       s.close()
diff --git a/tuerd b/tuerd
deleted file mode 100755 (executable)
index 942c495..0000000
--- a/tuerd
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/python3
-import RPi.GPIO as GPIO
-import statemachine, actor, pins, tysock, waker, spaceapi
-from libtuer import logger
-import argparse
-
-# Parse arguments
-parser = argparse.ArgumentParser(description='Run a door')
-parser.add_argument("-d", "--debug",
-                                       action="store_true", dest="debug",
-                                       help="Don't send emails")
-parser.add_argument("-f", "--fallback",
-                                       action="store_true", dest="fallback",
-                                       help="Fallback mode for unfunctional hardware: Depend on less sensor input")
-args = parser.parse_args()
-if args.debug:
-       import libtuer
-       libtuer.mailAddress = []
-if args.fallback:
-       logger.info("Starting in fallback mode")
-else:
-       # to avoid exceptions or getting None
-       args.fallback = False
-
-# Not let's go!
-logger.info("Starting up...")
-
-# initialize GPIO stuff
-GPIO.setmode(GPIO.BOARD)
-
-# bring 'em all up
-the_actor = actor.Actor()
-the_waker = waker.Waker()
-the_api   = spaceapi.SpaceApi(the_waker)
-the_machine = statemachine.StateMachine(the_actor, the_waker, the_api, args.fallback)
-the_socket = tysock.TySocket(the_machine)
-the_pins = pins.PinsWatcher(the_machine)
-
-# we do the socket accept thing in the main thread
-try:
-       the_socket.accept()
-except KeyboardInterrupt:
-       # this is what we waited for!
-       pass
-
-logger.info("Terminating...") # somehow this does not arrive in the syslog
-
-# bring 'em all down
-the_waker.stop() # this one first, it "randomly" calls other threads
-the_pins.stop() # as does this
-the_machine.stop()
-the_api.stop()
-the_actor.stop()
-
-# shutdown GPIO stuff
-GPIO.cleanup()
diff --git a/tyshell b/tyshell
deleted file mode 100755 (executable)
index b535f2b..0000000
--- a/tyshell
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/python3
-import os
-import readline
-import shlex
-import sys
-import subprocess
-import socket
-import pwd
-import grp
-import traceback
-from collections import namedtuple
-
-tuerSock = "/run/tuer.sock"
-
-# use a histfile
-histfile = os.path.join(os.path.expanduser("~"), ".tyshellhist")
-try:
-    readline.read_history_file(histfile)
-except IOError:
-    pass
-import atexit
-atexit.register(readline.write_history_file, histfile)
-
-# available commands
-def helpcmd(c):
-       if (len(c) > 1):
-               print(commands.get(c[1],(None,'Can\'t find help for command %s'%(c[1]))).helpstring)
-       else:
-               print("Available commands: %s" % ", ".join(sorted(commands.keys())))
-               print("Use 'help command' to get more information on the command 'command'")
-
-def extcmd(cmd):
-       def run(c):
-               ret = subprocess.call(cmd)
-               if ret != 0:
-                       print("Command returned non-zero exit statis %d" % ret)
-       return run
-
-def sendcmd(addr, cmd):
-       def run(c):
-               print("206 Sending command %s..." % (cmd))
-               s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-               s.connect(addr)
-               s.settimeout(60.0)
-               s.send(cmd.encode())
-               while True:
-                       data = s.recv(256)
-                       if not len(data): break
-                       print(data.decode('utf-8'))
-               s.close()
-       return run
-
-def exitcmd(c):
-       print("Bye")
-       return True
-
-def whocmd(c):
-       for n in grp.getgrnam("tuer").gr_mem:
-               p = pwd.getpwnam(n)
-               print (p.pw_name, " - ", p.pw_gecos)
-
-def alias (cmds, aliases):
-       for newname, oldname in aliases.items():
-               cmds[newname] = cmds[oldname]
-       return cmds
-
-def prompt_sure(f,msg):
-       def run(c):
-               try:
-                       command = input("%s Are you sure? (yes/no) > " % msg)
-               except EOFError:
-                       print()
-                       return
-               if command[0] == 'y':
-                       return f(c)
-       return run
-
-CmdEntry = namedtuple('CmdEntry','function helpstring')
-
-commands = alias({
-       'exit': CmdEntry(exitcmd, 'Quits this shell'),
-       'help': CmdEntry(helpcmd, 'Helps you getting to know the available commands'),
-       'unlock': CmdEntry(sendcmd(tuerSock, 'unlock'), 'Will try to unlock the apartment door'),
-       'lock': CmdEntry(sendcmd(tuerSock, 'lock'), 'If in fallback mode, try to lock the apartment door. If not in fallback mode, you must use the switch near the door.'),
-       'buzz': CmdEntry(sendcmd(tuerSock, 'buzz'), 'Will buzz the buzzer for the street door'),
-       'who': CmdEntry(whocmd, 'Shows the list of people, who are allowed to control this system'),
-       'fallback_mode_on': CmdEntry(prompt_sure(sendcmd(tuerSock, 'fallback_mode_on'),'WARNING: This action will be reported to the admins. Use this only in case of Sphinx hardware failure when you need to ignore erroneous sensor input!'), 'Sets the system in a state where it is less dependent on sensoric input. Use it only when sensors are broken.'),
-       'fallback_mode_off': CmdEntry(prompt_sure(sendcmd(tuerSock, 'fallback_mode_off'),'WARNING: This action will be reported to the admins. Use this only if you have fixed the sensors of the Sphinx or activated fallback mode by accident!'), 'Resets the system to the default state. Use this when you have just repaired the sensors of the Sphinx.'),
-       'status': CmdEntry(sendcmd(tuerSock, 'status'), 'Shows internal state and sensor information.'),
-},{
-       # aliases
-       'open': 'unlock',
-})
-
-def complete_command(cmd):
-       '''returns a list of commands (as strings) starting with cmd'''
-       return list(filter(lambda x: x.startswith(cmd), commands.keys()))
-readline.set_completer(lambda cmd, num: (complete_command(cmd)+[None])[num]) # wrap complete_command for readline's weird completer API
-readline.parse_and_bind("tab: complete") # run completion on tab
-
-# input loop
-print("Welcome to tyshell. Use help to see what you can do.")
-while True:
-       try:
-               command = input("$ ")
-       except EOFError:
-               print()
-               break
-       command = shlex.split(command)
-       if not len(command): continue
-       # find suiting commands
-       if command[0] in commands: # needed in case a complete command is a prefix of another one
-               cmdoptions = [command[0]]
-       else:
-               cmdoptions = complete_command(command[0])
-       # check how many we found
-       if len(cmdoptions) == 0: # no commands fit prefix
-               print("Command %s not found. Use help." % command[0])
-       elif len(cmdoptions) == 1: # exactly one command fits (prefix)
-               try:
-                       res = commands[cmdoptions[0]].function(command)
-                       if res: break
-               except Exception as e:
-                       print("Error while executing %s: %s" % (command[0], str(e)))
-                       #print(traceback.format_exc())
-       else: # multiple commands fit the prefix
-               print("Ambiguous command prefix, please choose one of the following:")
-               print("\t", " ".join(cmdoptions))
-               # TODO: put current "command[0]" into the shell for the next command, but such that it is deletable with backspace
-
diff --git a/tysock.py b/tysock.py
deleted file mode 100644 (file)
index b987567..0000000
--- a/tysock.py
+++ /dev/null
@@ -1,86 +0,0 @@
-import socket, os, stat, struct, pwd, errno
-from statemachine import StateMachine
-from libtuer import logger
-SO_PEERCRED = 17 # DO - NOT - TOUCH
-
-tuergroupid = 1005
-socketname = "/run/tuer.sock"
-
-# send to client for information but don't care if it arrives
-def waynesend (conn, what):
-       try:
-               conn.send(what.encode())
-       except:
-               pass # we do not care
-
-# delete a file, don't care if it did not exist in the first place
-def forcerm(name):
-       try:
-               os.unlink (name)
-       except OSError as e:
-               # only ignore error if it was "file didn't exist"
-               if e.errno != errno.ENOENT:
-                       raise
-
-# the class doing the actual work
-class TySocket():
-       CMDs = {
-               b'buzz': StateMachine.CMD_BUZZ,
-               b'unlock': StateMachine.CMD_UNLOCK,
-               b'lock': StateMachine.CMD_LOCK,
-               b'fallback_mode_on': StateMachine.CMD_FALLBACK_ON,
-               b'fallback_mode_off': StateMachine.CMD_FALLBACK_OFF,
-               b'status': StateMachine.CMD_STATUS,
-       }
-       
-       def __init__(self, sm):
-               self._sm = sm
-               # create socket
-               self._sock = socket.socket (socket.AF_UNIX, socket.SOCK_STREAM)
-               # delete old socket file and don't bitch around if it's not there
-               forcerm(socketname)
-               # bind socket to file name
-               self._sock.bind (socketname)
-               # allow only users in the tuergroup to write to the socket
-               os.chown (socketname, 0, tuergroupid)
-               os.chmod (socketname, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP)
-               # listen to the people, but not too many at once
-               self._sock.listen(1)
-       
-       def _answer(self, conn):
-               def answer(msg, lastMsg = True):
-                       # this is called in another thread, so it should be quick and not touch the TySocket
-                       waynesend(conn, msg)
-                       if lastMsg:
-                               conn.close()
-               return answer
-       
-       def accept(self):
-               '''Handles incoming connections and keyboard events'''
-               self._sock.settimeout(None)
-               while True:
-                       # accept connections
-                       conn, addr = self._sock.accept()
-                       conn.settimeout(0.1)
-                       try:
-                               # get peer information
-                               (pid, uid, gid) = struct.unpack('3i', conn.getsockopt(socket.SOL_SOCKET, SO_PEERCRED, struct.calcsize('3i')))
-                               # get some data from the client (enough to hold any valid command)
-                               data = conn.recv (32)
-                               # log the command
-                               logger.info("TySocket: Received command from %s (uid %d): %s" % (pwd.getpwuid(uid).pw_name, uid, str(data)))
-                               # lookup the command, send it to state machine
-                               if data in self.CMDs:
-                                       self._sm.callback(self.CMDs[data], self._answer(conn))
-                                       # _answer will be called, and it will close the connection
-                                       continue # make sure we break so we don't close it
-                               else:
-                                       waynesend(conn, 'Command not found')
-                       except KeyboardInterrupt:
-                               raise # forward Ctrl-C to the outside
-                       except socket.timeout:
-                               # it's okay
-                               logger.info("TySocket: Connection timed out")
-                       except Exception as e:
-                               logger.critical("TySocket: Something went wrong: %s" % str(e))
-                       conn.close()
diff --git a/waker.py b/waker.py
deleted file mode 100644 (file)
index 79eff81..0000000
--- a/waker.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from libtuer import ThreadRepeater
-from threading import Lock
-
-SLEEP_TIME = 0.5
-
-class ToBeWoken:
-       '''a simple struct storing information about a to-be-woken function'''
-       def __init__(self, f, period, one_shot):
-               self.f = f
-               self.period = period
-               self.time_since_call = 0
-               self.one_shot = one_shot
-
-class Waker():
-       def __init__(self):
-               self._tobewokens = []
-               self._tobewokens_lock = Lock()
-               self._t = ThreadRepeater(self._wake, SLEEP_TIME, name="Waker")
-       
-       def register(self, f, time, one_shot = False):
-               '''Register a function which is called approximately every <time> seconds (or just once, if one_shot is True). f should return quickly, or it will delay the waker!'''
-               time = max(time//SLEEP_TIME, 1)
-               with self._tobewokens_lock:
-                       self._tobewokens.append(ToBeWoken(f, time, one_shot))
-       
-       def _wake(self):
-               with self._tobewokens_lock:
-                       delete = []
-                       # run the functions we ought to run
-                       for tobewoken, idx in zip(self._tobewokens, range(len(self._tobewokens))):
-                               tobewoken.time_since_call += 1
-                               if tobewoken.time_since_call >= tobewoken.period:
-                                       tobewoken.f()
-                                       tobewoken.time_since_call = 0
-                                       if tobewoken.one_shot:
-                                               delete.append(idx)
-                       # delete what we have to delete - in reverse order so the indices stay valid!
-                       delete.reverse()
-                       for idx in delete:
-                               del self._tobewokens[idx]
-       
-       def stop(self):
-               self._t.stop()