Skip to content

Commit

Permalink
commit 9b880b58935ad9800efd1e91f0b046bff7f0fbbc
Browse files Browse the repository at this point in the history
Author: Rick van Schijndel <[email protected]>
Date:   Fri Jun 15 13:01:10 2018 +0200

    Remove real username and password

commit 02e054bd9516ef01cecd44d7f7868f6bf0540f1c
Author: Rick van Schijndel <[email protected]>
Date:   Wed Jun 13 18:16:41 2018 +0200

    Somewhat nicer interface for logging in

commit aa740994ee7090e93fc3b1d037874546ec0b0692
Author: Rick van Schijndel <[email protected]>
Date:   Mon Jun 11 11:58:22 2018 +0200

    Created a class to do the login flow

commit b891b30b6f7a7d07d59d1ce1746c2f464ab55c25
Author: Rick van Schijndel <[email protected]>
Date:   Mon Jun 11 07:36:00 2018 +0200

    Version bump to 1.2

commit 2edea884fd3005b6ed586b8a4eec0fed6bf55c8d
Author: Rick van Schijndel <[email protected]>
Date:   Mon Jun 11 07:33:40 2018 +0200

    Checks for connection and should handle errors better

    Still not in a flow I'm happy with, but it's better

commit 6e57e67f48f9841b03b231f3fbe1a5e6336a4c6b
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 22:02:09 2018 +0200

    Add simple explanation on how to use the script

commit a9acbeece64e309e40885545368f74013fa67719
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 22:01:47 2018 +0200

    Simplified the main logic by moving caching to functions itself

commit f024a699b26e6cd17ca916e4124c1e227ce6d6ef
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 21:54:57 2018 +0200

    Should handle errors more gracefully, slightly more verbose

commit a0f397e0b8328eb260cdbbc8232f9ae15ef355ac
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 21:50:47 2018 +0200

    More dynamic, is now aware of the users sites

commit d7d7c4928bdbb23cea7d67f0fd266c8f36f2da1e
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 21:03:01 2018 +0200

    Better script, will read login data from file and persist session cookie

commit 708e3de643c246902adfb848ee24ef73379f1eaf
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 19:52:34 2018 +0200

    Update version in gradle file

commit f0023c9049b5e4b6fd0580127d9a1b0c06ad678f
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 19:41:13 2018 +0200

    Nicer UI, before the text and graph were mixed up

commit 0864cb3bc7aab9662e0f51c66013a3dc88840d41
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 19:40:52 2018 +0200

    Sort data from json because order of the data is not guaranteed

    Tried to run the app on a device running android 4.1 (api version 16)
    and it crashed with the warning that the data must be sorted

    After debugging found out that the data is in 'random' order when
    processed by the json library on that android version

commit 1d7d0a4352313061dc7d025c7dce5343522c3f99
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 17:30:47 2018 +0200

    Change launcher icon, remove unused activity design

commit 22b2e34598db26ded526ffc8c99ce1436d582285
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 17:18:36 2018 +0200

    Add flow for logging in

commit 1bc83d99c16f9ff9946793fedf090fec17dee051
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 17:14:11 2018 +0200

    Retrieves data from network and parses it

    Slightly ugly code, but it works and I'm happy I got there

commit f38ce24fb99c3be1aadd0210cebc66dd00273881
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 15:34:54 2018 +0200

    Test script which retrieves data from the server using the login flow

commit ab48b7ef3bda37162e5db9421e640fc7716ce6b6
Author: Rick van Schijndel <[email protected]>
Date:   Sun Jun 10 14:39:34 2018 +0200

    Initial version, decoding json works with static dataset
  • Loading branch information
Mindavi committed Jun 15, 2018
0 parents commit bcb834f
Show file tree
Hide file tree
Showing 44 changed files with 1,132 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea
.DS_Store
/build
/captures
.externalNativeBuild
1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
40 changes: 40 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 27
defaultConfig {
applicationId "eu.rickvanschijndel.solargraph"
minSdkVersion 16
targetSdkVersion 27
versionCode 4
versionName "1.3"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.1'
implementation 'com.jjoe64:graphview:4.2.2'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.10.0'
implementation 'com.github.franmontiel:PersistentCookieJar:v1.0.1'
implementation 'org.jsoup:jsoup:1.11.3'

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package eu.rickvanschijndel.solargraph

import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getTargetContext()
assertEquals("eu.rickvanschijndel.solargraph", appContext.packageName)
}
}
25 changes: 25 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="eu.rickvanschijndel.solargraph">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".GraphActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Binary file added app/src/main/ic_launcher-web.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
159 changes: 159 additions & 0 deletions app/src/main/java/eu/rickvanschijndel/solargraph/GraphActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package eu.rickvanschijndel.solargraph

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.preference.PreferenceManager
import android.util.Log
import android.widget.Toast
import com.franmontiel.persistentcookiejar.PersistentCookieJar
import com.franmontiel.persistentcookiejar.cache.SetCookieCache
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor
import com.jjoe64.graphview.helper.DateAsXAxisLabelFormatter
import com.jjoe64.graphview.series.LineGraphSeries
import com.jjoe64.graphview.series.DataPoint
import kotlinx.android.synthetic.main.activity_graph.*
import okhttp3.*
import org.json.JSONObject
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*


class GraphActivity : AppCompatActivity(), LoginCallback {
private lateinit var client: OkHttpClient
private lateinit var cookieJar: PersistentCookieJar
private lateinit var login: Login
private var retries = 0

companion object {
private const val TAG = "GraphActivity"
private const val maxRetries = 3
}

override fun onUpdate(event: LoginCallback.LoginEvent, updateMessage: String?) {
when(event) {
LoginCallback.LoginEvent.STATUS_CHANGED -> {
runOnUiThread {
if (updateMessage != null) {
network_info.text = updateMessage
}
}
}
LoginCallback.LoginEvent.LOGGED_IN -> {
retrieveData()
retries = 0
}
LoginCallback.LoginEvent.NO_CREDENTIALS -> {
runOnUiThread {
network_info.setText(R.string.no_credentials)
}
}
LoginCallback.LoginEvent.LOGIN_FAILURE -> {
runOnUiThread {
network_info.setText(R.string.retry_logging_in)
retries++
if (retries <= maxRetries) {
login.login()
return@runOnUiThread
}
else {
network_info.setText(R.string.max_retries_exceeded)
}
}
}
}
}

private fun retrieveData() {
runOnUiThread {
network_info.setText(R.string.retrieving_data)
}
val request = Request.Builder()
.url("https://my.autarco.com/api/site/or0q8h99/inverter/current?i=410017621936")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call?, e: IOException?) {
e?.printStackTrace()
}

override fun onResponse(call: Call?, response: Response?) {
if (response == null || !response.isSuccessful) {
if (response != null) {
Log.d(TAG, response.message())
runOnUiThread {
network_info.text = response.message()
}
if (response.code() == 401) {
cookieJar.clear()
}
}
Log.d(TAG, "Invalid response")
return
}
val responseData = response.body()?.string() ?: return
onDataRetrieved(responseData)
}
})
}


private fun onDataRetrieved(responseData: String) {
val jsonObject = JSONObject(responseData).getJSONObject("stats").getJSONObject("graphs").getJSONObject("realtime_power")
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US)
var dataPoints = arrayOf<DataPoint>()
for (key in jsonObject.keys()) {
val power = jsonObject.getDouble(key)
val date = formatter.parse(key)
dataPoints += DataPoint(date, power)
}

val sortedDataPoints = dataPoints.sortedWith(compareBy({it.x}))

val series = LineGraphSeries(sortedDataPoints.toTypedArray())
runOnUiThread {
network_info.setText(R.string.got_data)
graph.addSeries(series)
val timeFormatter = SimpleDateFormat("HH:00", Locale.US)
graph.gridLabelRenderer.labelFormatter = DateAsXAxisLabelFormatter(this, timeFormatter)
val firstPower = sortedDataPoints.first { it.y > 0}
val lastPower = sortedDataPoints.last{ it.y > 0}
graph.viewport.setMinX(firstPower.x)
graph.viewport.setMaxX(lastPower.x)
graph.viewport.isXAxisBoundsManual = true
graph.viewport.setMaxY(series.highestValueY)
graph.viewport.isYAxisBoundsManual = true
series.setOnDataPointTapListener { _, dataPoint ->
Toast.makeText(this, "Power: ${dataPoint.y}W", Toast.LENGTH_SHORT).show()
}
}
}

private fun getActiveNetworkInfo(): NetworkInfo {
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return connectivityManager.activeNetworkInfo
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_graph)

cookieJar = PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(this))
client = OkHttpClient.Builder()
.cookieJar(cookieJar)
.build()
login = Login(this, client)

val networkInfo = getActiveNetworkInfo()
if (!networkInfo.isConnected)
{
network_info.setText(R.string.no_connection)
return
}
login.setUsername("username")
login.setPassword("password")
login.login()
}
}
Loading

0 comments on commit bcb834f

Please sign in to comment.