diff --git a/.gitignore b/.gitignore
index 08597d2..ecee633 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,7 +17,6 @@ dist/
downloads/
eggs/
.eggs/
-lib/
lib64/
parts/
sdist/
diff --git a/android/.gitignore b/android/.gitignore
new file mode 100644
index 0000000..c6cbe56
--- /dev/null
+++ b/android/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/android/.idea/.name b/android/.idea/.name
new file mode 100644
index 0000000..86beff4
--- /dev/null
+++ b/android/.idea/.name
@@ -0,0 +1 @@
+Farm Alarm
\ No newline at end of file
diff --git a/android/.idea/compiler.xml b/android/.idea/compiler.xml
new file mode 100644
index 0000000..96cc43e
--- /dev/null
+++ b/android/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ * This class makes heavy use of the {@link NotificationCompat.Builder} helper + * class to create notifications in a backward-compatible way. + */ +public class AlarmNotification { + /** + * The unique identifier for this type of notification. + */ + private static final String NOTIFICATION_TAG = "Alarm"; + + /** + * Shows the notification, or updates a previously shown notification of + * this type, with the given parameters. + *
+ * TODO: Customize this method's arguments to present relevant content in + * the notification. + *
+ * TODO: Customize the contents of this method to tweak the behavior and + * presentation of alarm notifications. Make + * sure to follow the + * + * Notification design guidelines when doing so. + * + * @see #cancel(Context) + */ + public static void notify(final Context context, + final String exampleString, final int number) { + final Resources res = context.getResources(); + + // This image is used as the notification's large icon (thumbnail). + // TODO: Remove this if your notification has no relevant thumbnail. + final Bitmap picture = BitmapFactory.decodeResource(res, R.drawable.example_picture); + + + final String ticker = exampleString; + final String title = res.getString( + R.string.alarm_notification_title_template, exampleString); + final String text = res.getString( + R.string.alarm_notification_placeholder_text_template, exampleString); + + final NotificationCompat.Builder builder = new NotificationCompat.Builder(context) + + // Set appropriate defaults for the notification light, sound, + // and vibration. + .setDefaults(Notification.DEFAULT_ALL) + + // Set required fields, including the small icon, the + // notification title, and text. + .setSmallIcon(R.drawable.ic_stat_alarm) + .setContentTitle(title) + .setContentText(text) + + // All fields below this line are optional. + + // Use a default priority (recognized on devices running Android + // 4.1 or later) + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + + // Provide a large icon, shown with the notification in the + // notification drawer on devices running Android 3.0 or later. + .setLargeIcon(picture) + + // Set ticker text (preview) information for this notification. + .setTicker(ticker) + + // Show a number. This is useful when stacking notifications of + // a single type. + .setNumber(number) + + // If this notification relates to a past or upcoming event, you + // should set the relevant time information using the setWhen + // method below. If this call is omitted, the notification's + // timestamp will by set to the time at which it was shown. + // TODO: Call setWhen if this notification relates to a past or + // upcoming event. The sole argument to this method should be + // the notification timestamp in milliseconds. + //.setWhen(...) + + // Set the pending intent to be initiated when the user touches + // the notification. + .setContentIntent( + PendingIntent.getActivity( + context, + 0, + new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com")), + PendingIntent.FLAG_UPDATE_CURRENT)) + // Automatically dismiss the notification when it is touched. + .setAutoCancel(true); + + notify(context, builder.build()); + } + + @TargetApi(Build.VERSION_CODES.ECLAIR) + private static void notify(final Context context, final Notification notification) { + final NotificationManager nm = (NotificationManager) context + .getSystemService(Context.NOTIFICATION_SERVICE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) { + nm.notify(NOTIFICATION_TAG, 0, notification); + } else { + nm.notify(NOTIFICATION_TAG.hashCode(), notification); + } + } + + /** + * Cancels any notifications of this type previously shown using + * {@link #notify(Context, String, int)}. + */ + @TargetApi(Build.VERSION_CODES.ECLAIR) + public static void cancel(final Context context) { + final NotificationManager nm = (NotificationManager) context + .getSystemService(Context.NOTIFICATION_SERVICE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) { + nm.cancel(NOTIFICATION_TAG, 0); + } else { + nm.cancel(NOTIFICATION_TAG.hashCode()); + } + } +} diff --git a/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/AlarmPollingService.java b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/AlarmPollingService.java new file mode 100644 index 0000000..6636052 --- /dev/null +++ b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/AlarmPollingService.java @@ -0,0 +1,62 @@ +package com.zoblak.farmalarm; + +import android.app.IntentService; +import android.content.Intent; +import android.content.Context; + +/** + * An {@link IntentService} subclass for handling asynchronous task requests in + * a service on a separate handler thread. + *
+ * TODO: Customize class - update intent actions, extra parameters and static + * helper methods. + */ +public class AlarmPollingService extends IntentService { + // TODO: Rename actions, choose action names that describe tasks that this + // IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS + private static final String ACTION_PING = "com.zoblak.farmalarm.action.PING"; + + // TODO: Rename parameters + private static final String CONTROLLERS = "com.zoblak.farmalarm.extra.CONTROLLLERS"; + + + public AlarmPollingService() { + super("AlarmPollingService"); + } + + /** + * Starts this service to perform action Foo with the given parameters. If + * the service is already performing a task this action will be queued. + * + * @see IntentService + */ + // TODO: Customize helper method + public static void startActionPing(Context context, String controllers) { + Intent intent = new Intent(context, AlarmPollingService.class); + intent.setAction(ACTION_PING); + intent.putExtra(CONTROLLERS, controllers); + context.startService(intent); + } + + + @Override + protected void onHandleIntent(Intent intent) { + if (intent != null) { + final String action = intent.getAction(); + if (ACTION_PING.equals(action)) { + final String controllers = intent.getStringExtra(CONTROLLERS); + handleActionPing(controllers); + } + } + } + + /** + * Handle action Foo in the provided background thread with the provided + * parameters. + */ + private void handleActionPing(String controllers) { + // do something + + } + +} diff --git a/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/AppCompatPreferenceActivity.java b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/AppCompatPreferenceActivity.java new file mode 100644 index 0000000..4d150bd --- /dev/null +++ b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/AppCompatPreferenceActivity.java @@ -0,0 +1,109 @@ +package com.zoblak.farmalarm; + +import android.content.res.Configuration; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.support.annotation.LayoutRes; +import android.support.annotation.Nullable; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatDelegate; +import android.support.v7.widget.Toolbar; +import android.view.MenuInflater; +import android.view.View; +import android.view.ViewGroup; + +/** + * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls + * to be used with AppCompat. + */ +public abstract class AppCompatPreferenceActivity extends PreferenceActivity { + + private AppCompatDelegate mDelegate; + + @Override + protected void onCreate(Bundle savedInstanceState) { + getDelegate().installViewFactory(); + getDelegate().onCreate(savedInstanceState); + super.onCreate(savedInstanceState); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + getDelegate().onPostCreate(savedInstanceState); + } + + public ActionBar getSupportActionBar() { + return getDelegate().getSupportActionBar(); + } + + public void setSupportActionBar(@Nullable Toolbar toolbar) { + getDelegate().setSupportActionBar(toolbar); + } + + @Override + public MenuInflater getMenuInflater() { + return getDelegate().getMenuInflater(); + } + + @Override + public void setContentView(@LayoutRes int layoutResID) { + getDelegate().setContentView(layoutResID); + } + + @Override + public void setContentView(View view) { + getDelegate().setContentView(view); + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().setContentView(view, params); + } + + @Override + public void addContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().addContentView(view, params); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getDelegate().onPostResume(); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + super.onTitleChanged(title, color); + getDelegate().setTitle(title); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getDelegate().onConfigurationChanged(newConfig); + } + + @Override + protected void onStop() { + super.onStop(); + getDelegate().onStop(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + getDelegate().onDestroy(); + } + + public void invalidateOptionsMenu() { + getDelegate().invalidateOptionsMenu(); + } + + private AppCompatDelegate getDelegate() { + if (mDelegate == null) { + mDelegate = AppCompatDelegate.create(this, null); + } + return mDelegate; + } +} diff --git a/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/MainScreen.java b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/MainScreen.java new file mode 100644 index 0000000..352c703 --- /dev/null +++ b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/MainScreen.java @@ -0,0 +1,52 @@ +package com.zoblak.farmalarm; + +import android.os.Bundle; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.Snackbar; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.view.Menu; +import android.view.MenuItem; + +public class MainScreen extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main_screen); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_main_screen, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + + //noinspection SimplifiableIfStatement + if (id == R.id.action_settings) { + return true; + } + + return super.onOptionsItemSelected(item); + } +} diff --git a/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/MainScreenFragment.java b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/MainScreenFragment.java new file mode 100644 index 0000000..98b9453 --- /dev/null +++ b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/MainScreenFragment.java @@ -0,0 +1,34 @@ +package com.zoblak.farmalarm; + +import android.support.v4.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebSettings; +import android.webkit.WebView; + +/** + * A placeholder fragment containing a simple view. + */ +public class MainScreenFragment extends Fragment { + + public MainScreenFragment() { + + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + View view = inflater.inflate(R.layout.fragment_main_screen, container, false); + + WebView webView = (WebView)view.findViewById(R.id.main_web_view); + WebSettings webSettings = webView.getSettings(); + webSettings.setJavaScriptEnabled(true); + webView.loadUrl("http://agrar.zoblak.com/alarm"); + + return view; + } +} diff --git a/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/PeriodicalPingReceiver.java b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/PeriodicalPingReceiver.java new file mode 100644 index 0000000..64e82d9 --- /dev/null +++ b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/PeriodicalPingReceiver.java @@ -0,0 +1,24 @@ +package com.zoblak.farmalarm; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +public class PeriodicalPingReceiver extends BroadcastReceiver { + public PeriodicalPingReceiver() { + } + + @Override + public void onReceive(Context context, Intent intent) { + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + String controllers = prefs.getString("controllers", null); + Boolean isAlarmOn = prefs.getBoolean("alarm_set", false); + + if(isAlarmOn && controllers != null) { + AlarmPollingService.startActionPing(context, controllers); + } + } +} diff --git a/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/SettingsActivity.java b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/SettingsActivity.java new file mode 100644 index 0000000..a65d68e --- /dev/null +++ b/android/FarmAlarm/app/src/main/java/com/zoblak/farmalarm/SettingsActivity.java @@ -0,0 +1,208 @@ +package com.zoblak.farmalarm; + + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.media.Ringtone; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; +import android.support.v7.app.ActionBar; +import android.preference.PreferenceFragment; +import android.preference.PreferenceManager; +import android.preference.RingtonePreference; +import android.text.TextUtils; +import android.view.MenuItem; +import android.support.v4.app.NavUtils; + +import java.util.List; + +/** + * A {@link PreferenceActivity} that presents a set of application settings. On + * handset devices, settings are presented as a single list. On tablets, + * settings are split by category, with category headers shown to the left of + * the list of settings. + *
+ * See
+ * Android Design: Settings for design guidelines and the Settings
+ * API Guide for more information on developing a Settings UI.
+ */
+public class SettingsActivity extends AppCompatPreferenceActivity {
+ /**
+ * A preference value change listener that updates the preference's summary
+ * to reflect its new value.
+ */
+ private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object value) {
+ String stringValue = value.toString();
+
+ if (preference instanceof ListPreference) {
+ // For list preferences, look up the correct display value in
+ // the preference's 'entries' list.
+ ListPreference listPreference = (ListPreference) preference;
+ int index = listPreference.findIndexOfValue(stringValue);
+
+ // Set the summary to reflect the new value.
+ preference.setSummary(
+ index >= 0
+ ? listPreference.getEntries()[index]
+ : null);
+
+ } else if (preference instanceof RingtonePreference) {
+ // For ringtone preferences, look up the correct display value
+ // using RingtoneManager.
+ if (TextUtils.isEmpty(stringValue)) {
+ // Empty values correspond to 'silent' (no ringtone).
+ //preference.setSummary(R.string.pref_ringtone_silent);
+
+ } else {
+ Ringtone ringtone = RingtoneManager.getRingtone(
+ preference.getContext(), Uri.parse(stringValue));
+
+ if (ringtone == null) {
+ // Clear the summary if there was a lookup error.
+ preference.setSummary(null);
+ } else {
+ // Set the summary to reflect the new ringtone display
+ // name.
+ String name = ringtone.getTitle(preference.getContext());
+ preference.setSummary(name);
+ }
+ }
+
+ } else {
+ // For all other preferences, set the summary to the value's
+ // simple string representation.
+ preference.setSummary(stringValue);
+ }
+ return true;
+ }
+ };
+
+ /**
+ * Helper method to determine if the device has an extra-large screen. For
+ * example, 10" tablets are extra-large.
+ */
+ private static boolean isXLargeTablet(Context context) {
+ return (context.getResources().getConfiguration().screenLayout
+ & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ }
+
+ /**
+ * Binds a preference's summary to its value. More specifically, when the
+ * preference's value is changed, its summary (line of text below the
+ * preference title) is updated to reflect the value. The summary is also
+ * immediately updated upon calling this method. The exact display format is
+ * dependent on the type of preference.
+ *
+ * @see #sBindPreferenceSummaryToValueListener
+ */
+ private static void bindPreferenceSummaryToValue(Preference preference) {
+ // Set the listener to watch for value changes.
+ preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
+
+ // Trigger the listener immediately with the preference's
+ // current value.
+ sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
+ PreferenceManager
+ .getDefaultSharedPreferences(preference.getContext())
+ .getString(preference.getKey(), ""));
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setupActionBar();
+ }
+
+ /**
+ * Set up the {@link android.app.ActionBar}, if the API is available.
+ */
+ private void setupActionBar() {
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ // Show the Up button in the action bar.
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+ }
+
+ @Override
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {
+ int id = item.getItemId();
+ if (id == android.R.id.home) {
+ if (!super.onMenuItemSelected(featureId, item)) {
+ NavUtils.navigateUpFromSameTask(this);
+ }
+ return true;
+ }
+ return super.onMenuItemSelected(featureId, item);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onIsMultiPane() {
+ return isXLargeTablet(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public void onBuildHeaders(List Temperatura
+
+
+ {{/if}}
+ {{/with}}
+ {{#with last_reading}}
+