數據科學英語:data science),又稱資料科學,是一門利用數據學習知識的學科,其目標是通過從數據中提取出有價值的部分來生產數據產品[1]。它結合了諸多領域中的理論和技術,包括應用數學統計模式識別機器學習數據可視化數據倉庫以及高性能計算。數據科學通過運用各種相關的數據來幫助非專業人士理解問題。 數據科學技術可以幫助我們如何正確的處理數據並協助我們在生物學社會科學人類學等領域進行研究調研。此外,數據科學也對商業競爭有極大的幫助。

資料科學學習路徑

「data science learning path」的圖片搜尋結果

資料科學學科

 

資料科學自學工具

「data science python」的圖片搜尋結果

資料科學自學參考網站

(1)How to Improve Your Domain Knowledge

1. Research – I once worked on a project that involved the development of an MRP application. At the start of the project, I felt overwhelmed and completely out of my comfort zone. I knew I had to get up to speed and fast. I downloaded as many papers and case studies as I could find online and read up on what other businesses in the industry were doing. It took time and sweat but it eventually paid off. I eventually started “talking the talk”.

2. Interview Key Stakeholders – Arrange to meet with subject matter experts. This meeting can be an informal meeting in a café or a workshop setting. Stakeholders are usually open to providing information if they know the benefits that are likely to come their way if they do. The more knowledgeable the stakeholder, the better. Start with open-ended questions before asking specific questions. The more open-ended the questions are, the more you will learn.
To learn, you need to ask questions. The quality of follow-up questions you can ask however, depends largely on how well you understand the domain – a typical chicken and egg situation.Note that there's a limit to how many fundamental questions about the domain you can ask stakeholders. They may start to lose confidence in your abilities if they have to start explaining the “basic” principles of the domain to you. 3. Keep a Knowledge Book  For any project I start in a new domain, I keep what I like to call a “Knowledge Book”. In this excel workbook, I enter all the information I have gathered about the domain – process information, participants, facts, definitions and acronyms related to the domain. This book becomes my faithful companion and ever-reliable reference guide.

4. Immerse Yourself – Immerse yourself in the domain by talking to users and subscribing to newsletters that provide industry updates. Be in a state of continually seeking the knowledge you need to deliver the expected benefits. For example, if you're in the insurance industry, subscribe to websites like Insurance Times for regular updates.

5. Gain Industry Certification - This is a longer and perhaps tougher route and you may not have enough time if you are working on a fast-paced project. This route is however, preferable if you would like to have a deep knowledge of a specific business area. The CPA accreditation for example, is designed for accountants, CEHA for real estate and CLP for Logistics Professionals, to mention a few. Decide what level of knowledge you would like to attain and find out how much experience you need to proceed with the certification.

6. Find Training Courses: Take advantage of free courses online that teach fundamental concepts in specific domains. Here's an article on this: Improve Your Domain Knowledge With This List Of Free Courses

(2)Understanding the Business Domain

Here are some thoughts about the questions to ask and answer to get a high-level understanding of how a business works.

  1. Who is the customer?
  2. What is the product?
  3. How is the product sold? (online, phone, in-person sales)
  4. What is the cost structure of the product? (subscription, pay-per-unit, etc)
  5. Where does the money go?
  6. How do we fulfill or distribute the product?
  7. How do we produce or service the product?
  8. How do we support the customer?
  9. How do we market the product?
  10. What partners do we work with to do business? How do we manage these relationships?
  11. What information does the organization manage? Who is responsible for creating, updating, and retiring information? What systems are used to manage the information

(3) 8 Proven Ways To Increase Your Domain Knowledge In A Project

1. Research What Knowledge To Build
2. Ask Questions
3. Sign Up For A Course
4. Attend Industry Events
5. Build A Knowledge Base
6. Join A Knowledge Community
7. Find A Mentor
8. Offer Your Services

 

 

 

 

 

 

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

「桃園製」掃地機器人 前聯發科工程師如何成功離職創業?
特點:
(1) 「吸、乾擦、噴、拖」四合一功能的掃地機器人
(2)  擦玻璃機器人
(3) 破解掃地機器人的三大障礙
      (1)市面上掃地機器人,發現主要有兩種模式,純乾掃型機器人和滲水型機器人。人性理想的狀態應該是,要能讓使用者懶到底,機器人掃過後要無灰乾爽。
      (2)跨過iRobot、LG等大廠建立的專利牆。
      (3)建立價格優勢
(4) 獨家導航技術,比iRobot、小米便宜五~七倍   

     他拆解掃地機器人最重要的導航功能,發現目前有兩大技術陣營。
一種是影像式,也就是iRobot與LG使用的技術,整個影像辨識加上運算模組要20多美元。
另一類是LDS雷射雷達模式,這是小米掃地機器人使用的,整個模組要更貴,超過30美元。
但上面兩種設計, 會踩到別人的專利,於是重新研發產品架構。以手機用的簡易雷射IC偵測居家環境。
在機器人兩側及前端裝上共三把雷射,成本才四美元,卻可偵測周邊兩公尺距離,而且所需的演算法遠比影像辨識的小巧簡易,更節省相關零件成本。

 #--------------------------------------
想買掃地機器人?先思考5件事

購買前5個考量事項
根據資策會的報告顯示,評價掃地機器人有兩大指標:清潔率和覆蓋率。
真空吸力是清潔率的指標之一,家電達人陳浩文(電小二)指出,產品從800帕到2000帕都有,愈高吸力愈強、清潔力愈好;第二是覆蓋率,「掃地機器人運作時最重要的是知道自己在哪裡、走過哪裡、哪些地方沒走到,」而這三者就是路徑規畫的技術,跟機器人類型有關。

考量一、先了解兩大機器人類型
購買掃地機器人最重要的是,要先了解規畫式和隨機式掃地機器人的差別及優缺點

 

考量二、居家隔局、坪數

套房、雅房、三房兩廳等格局,各有適合的掃地機器人類型。「隨機式掃地機器人如同矇眼閉耳的人行走,直線前進,碰到牆壁就轉彎往回走,因此無法記憶和辨識走到哪裡或哪裡沒掃到,」單純的格局如套房、雅房較適合隨機式的掃地機器人。

而規畫式機器人會設定和記憶路徑、依照四周物體辨識所在位置及方向,三房兩廳或更加複雜的格局就建議使用規劃式掃地機器人,「它會知道和規劃路線,例如按著天花板行走,可以確保每個空間都掃到,」

但樓梯是掃地機器人的致命傷。雖然掃地機器人都有懸崖偵測裝置,一般不用擔心會摔下樓,但還沒有開發出會爬樓梯的機器人。所以樓中樓或透天厝就不建議使用,如果要用可以每層樓放一台,或在機器人掃完一層後,再把機器人移到另一層樓。此外樓梯口也需避免堆放東西,以免機器人因機身後方無偵測裝置而在倒退規避時不慎跌落

坪數是另一個考慮的地方。一般掃地機器人充電完畢可工作1-1.5小時,因此30坪以內的空間可以一次清掃完畢;但如果是50、60坪的大空間,可能就得分兩次清掃。
 

考量三、家具底下的空間高低

家具底下空間的高低也關係到機器人的選購。規畫式掃地機器人可能會搭載雷射頭、機身較高,有些過低的空間就無法進入打掃。
如果家具高度普遍較低,可以使用墊片撐高些許高度,或乾脆使用一般吸塵器就好。

 

考量四、地面平整及整齊度

不論是耐磨木地板、大理石、磁磚地面或鋪設巧拼,只要沒有巨大的坑洞、凹凸不平或落差太大(可以克服1.5公分厚的巧拼),機器人都能勝任工作。但是地毯,尤其是長毛地毯會卡住掃頭和輪子,讓機器人停止運作。

此外如果地板物品太多,例如家具、積木、盒子、瓶罐,塑膠袋、電線等,也不適合使用掃地機器人,因此使用前要先將地板雜物清除。

掃拖合一機器人另一個需要考慮的是家中地板落差,因為機器搭載水箱和抹布,跨越障礙物的能力較差,有些如1.5公分厚的巧拼都難以跨越。最後是抹布要勤更換,因有些產品本身吸力不強,清掃是依賴抹布,抹布髒得很快,不換會愈拖愈髒。

但如果對於地板清潔度要求不高、地板落差不大,要使用也是可以的。

考量五、寵物的居家生活

掃地機器人運作聲音雖然比吸塵器小,但如果寵物對聲音或移動物體較敏感而有焦躁不安的情形,使用時就應該讓寵物避開或隔離,
「機器人擅長處理棉絮、毛髮、沙塵,但對於液體沒轍。如果寵物不小心在家中便溺,使用時也要先清理乾淨,不然機器人會把糞便、尿液拖得到處都是,且有機率因吸入液體而導致機器損壞。」

 

 

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

Quick Reference NEMA size 17 1.8° 2-phase stepper motor(參考手冊)

https://reprap.org/wiki/NEMA_17_Stepper_motor (簡單規格)
Step Motor 42BYGH47-401A (規格),

1.8° It has 200 steps per revolution, and can operate at at 60 RPM,

Step Angle: 1.8°
Voltage: 24
Phase Current: 1.5A/Phase
Phase Resistance: 1.6ohm/Phase 
Phase inductance: 2.8mH/Phase
Holding Torque: 5500g.cm
Lead Wire: 4
中文規格說明

https://tutorials-raspberrypi.com/how-to-control-a-stepper-motor-with-raspberry-pi-and-l293d-uln2003a/ (程式)

https://www.electronicshub.org/raspberry-pi-stepper-motor-control/ (接線)

https://www.raspberrypi.org/forums/viewtopic.php?t=55580 (接線)

undefined

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
control_pins = [7,11,13,15]
for pin in control_pins:
  GPIO.setup(pin, GPIO.OUT)
  GPIO.output(pin, 0)
halfstep_seq = [
  [1,0,0,0],
  [1,1,0,0],
  [0,1,0,0],
  [0,1,1,0],
  [0,0,1,0],
  [0,0,1,1],
  [0,0,0,1],
  [1,0,0,1]
]
for i in range(512):
  for halfstep in range(8):
    for pin in range(4):
      GPIO.output(control_pins[pin], halfstep_seq[halfstep][pin])
    time.sleep(0.001)
GPIO.cleanup()

 

stanley 發表在 痞客邦 留言(0) 人氣()

https://www.androidhive.info/2013/11/android-working-with-action-bar/

Overview of Action Bar

undefined

Overflow Control

https://www.techotopia.com/index.php/Creating_and_Managing_Overflow_Menus_on_Android
https://www.dev2qa.com/android-custom-overflow-menu-example/

 

stanley 發表在 痞客邦 留言(0) 人氣()

https://towardsdatascience.com/how-tracking-apps-analyse-your-gps-data-a-hands-on-tutorial-in-python-756d4db6715d

stanley 發表在 痞客邦 留言(0) 人氣()

參考資料: Android Best Practices

這篇是一個範例如何將傳統的寫寫法變成MVC的架構

傳統寫法: there are two Java files we will work with, TodoActivity.java, shown in Listing 2-1, 
and TodoProvider.java, which you’ll see in Listing 2-2.

Listing 2-1.  TodoActivity.java
package com.logicdrop.todos;
 
import java.util.ArrayList;
import java.util.List;
 
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.os.StrictMode;
 
public class TodoActivity extends Activity
{
   public static final String APP_TAG = "com.logicdrop.todos";
 
   private ListView taskView;
   private Button btNewTask;
   private EditText etNewTask;
   private TodoProvider provider;
 
   private OnClickListener handleNewTaskEvent = new OnClickListener()
   {
       @Override
       public void onClick(final View view)
       {
          Log.d(APP_TAG, "add task click received");
 
          TodoActivity.this.provider.addTask(TodoActivity.this
                 .getEditText()
                 .getText()
                 .toString()); 
          TodoActivity.this.renderTodos();
       }
   };

   @Override
   protected void onStart()
   {
       super.onStart();
   }
   private void createPlaceholders()
   {
       this.getProvider().deleteAll();
       if (this.getProvider().findAll().isEmpty())
       {
          List<String> beans = new ArrayList<String>();
          for (int i = 0; i < 10; i++)
          {
              String title = "Placeholder " + i;
              this.getProvider().addTask(title);
              beans.add(title);
          }
       }
   }
   EditText getEditText()
   {
       return this.etNewTask;
   }
   private TodoProvider getProvider()
   {
       return this.provider;
   }
   private ListView getTaskView()
   {
       return this.taskView;
   }
   public void onCreate(final Bundle bundle)
   {
        super.onCreate(bundle);
        this.setContentView(R.layout.main);
       this.provider = new TodoProvider(this);
       this.taskView = (ListView) this.findViewById(R.id.tasklist);
       this.btNewTask = (Button) this.findViewById(R.id.btNewTask);
       this.etNewTask = (EditText) this.findViewById(R.id.etNewTask);
       this.btNewTask.setOnClickListener(this.handleNewTaskEvent);
       this.showFloatVsIntegerDifference(); 
       this.createPlaceholders(); 
       this.renderTodos();
  }
 
       private void renderTodos()
       {
       List<String> beans = this.getProvider().findAll();
 
       Log.d(APP_TAG, String.format("%d beans found", beans.size()));
 
       this.getTaskView().setAdapter(
              new ArrayAdapter<String>(this,
                     android.R.layout.simple_list_item_1, beans
                            .toArray(new String[]
                            {})));
 
       this.getTaskView().setOnItemClickListener(new OnItemClickListener()
       {
          @Override
          public void onItemClick(final AdapterView<?> parent,
                 final View view, final int position, final long id)
          {
              Log.d(APP_TAG, String.format(
                     "item with id: %d and position: %d", id, position));
 
              TextView v = (TextView) view;
              TodoActivity.this.getProvider().deleteTask(
                     v.getText().toString());
              TodoActivity.this.renderTodos();
          }
       });
   } 
}

TodoActivity.java controls the layout of the app, and TodoProvider.java, shown in Listing 2-2, 
manages the data for the items you add to your list. In the app we’ve populated it with a list of initial 
placeholder items.
Listing 2-2.  TodoProvider.java

package com.logicdrop.todos;
 
import java.util.ArrayList;
import java.util.List;
 
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
 
import com.logicdrop.todos.TodoActivity;
 
public class TodoProvider
{
   private static final String DB_NAME = "tasks";
   private static final String TABLE_NAME = "tasks";
   private static final int DB_VERSION = 1;
   private static final String DB_CREATE_QUERY = "CREATE TABLE " + TABLE_NAME + " (id integer 
primary key autoincrement, title text not null);";
 
   private SQLiteDatabase storage;
   private SQLiteOpenHelper helper;
 
   public TodoProvider(final Context ctx)
   {
       this.helper = new SQLiteOpenHelper(ctx, DB_NAME, null, DB_VERSION)
       {
          @Override
          public void onCreate(final SQLiteDatabase db)
          {
              db.execSQL(DB_CREATE_QUERY);
          }
 
          @Override
          public void onUpgrade(final SQLiteDatabase db, final int oldVersion,
                 final int newVersion)
          {
              db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
              this.onCreate(db);
          }
       };
 
       this.storage = this.helper.getWritableDatabase();
   }
 
   public synchronized void addTask(final String title)
   {
       ContentValues data = new ContentValues();
       data.put("title", title);
 
       this.storage.insert(TABLE_NAME, null, data);
   }
 
   public synchronized void deleteAll()
   {
       this.storage.delete(TABLE_NAME, null, null);
   }
 
   public synchronized void deleteTask(final long id)
   {
       this.storage.delete(TABLE_NAME, "id=" + id, null);
   }
   public synchronized void deleteTask(final String title)
   {
       this.storage.delete(TABLE_NAME, "title='" + title + "'", null);
   }
 
   public synchronized List<String> findAll()
   {
       Log.d(TodoActivity.APP_TAG, "findAll triggered");
 
       List<String> tasks = new ArrayList<String>();
 
       Cursor c = this.storage.query(TABLE_NAME, new String[] { "title" }, null, null, null, null, null);
 
       if (c != null)
       {
          c.moveToFirst(); 
          while (c.isAfterLast() == false)
          {
              tasks.add(c.getString(0));
              c.moveToNext();
          } 
          c.close();
       } 
       return tasks;
   }
}

 

MVC 架構設計Android 
MVC (Model-View-Controller) 

The Model
The MVC Model component, shown in Listing 2-10, largely replaces the ToDoProvider.java code from before.
Listing 2-10.  MVC Model code

final class TodoModel
{
    private static final String DB_NAME = "tasks";
    private static final String TABLE_NAME = "tasks";
    private static final int DB_VERSION = 1;
    private static final String DB_CREATE_QUERY = "CREATE TABLE " + TodoModel.TABLE_NAME +  
    " (id integer primary key autoincrement, title text not null);";
 
    private final SQLiteDatabase storage;
    private final SQLiteOpenHelper helper;
  
    public TodoModel(final Context ctx)
    {
        this.helper = new SQLiteOpenHelper(ctx, TodoModel.DB_NAME, null, TodoModel.DB_VERSION)
        {
            @Override
            public void onCreate(final SQLiteDatabase db)
            {
                db.execSQL(TodoModel.DB_CREATE_QUERY);
            }
 
            @Override
            public void onUpgrade(final SQLiteDatabase db, final int oldVersion,
                                  final int newVersion)
            {
                db.execSQL("DROP TABLE IF EXISTS " + TodoModel.TABLE_NAME);
                this.onCreate(db);
            }
        };
 
        this.storage = this.helper.getWritableDatabase();
    }
 
    public void addEntry(ContentValues data)
    {
        this.storage.insert(TodoModel.TABLE_NAME, null, data);
    }
 
    public void deleteEntry(final String field_params)
    {
        this.storage.delete(TodoModel.TABLE_NAME, field_params, null);
    }
 
    public Cursor findAll()
    {
        Log.d(TodoActivity.APP_TAG, "findAll triggered");
 
        final Cursor c = this.storage.query(TodoModel.TABLE_NAME, new String[]
                { "title" }, null, null, null, null, null);
 
        return c;
    }
}


The View
The View code in MVC, shown in Listing 2-11, is a modified version of the ToDoActivity.java 
code from before. Any UI changes now happen here, and the control code is now moved to the 
ToDoController.java file. 
Listing 2-11.  MVC View code


public class TodoActivity extends Activity
{
    public static final String APP_TAG = "com.example.mvc";
 
    private ListView taskView;
    private Button btNewTask;
    private EditText etNewTask;
 
    /*Controller changes are transparent to the View. UI changes won't
     *affect logic, and vice-versa. See below: the TodoModel has
     * been replaced with the TodoController, and the View persists
     * without knowledge that the implementation has changed.
     */
    private TodoController provider;
 
    private final OnClickListener handleNewTaskEvent = new OnClickListener()
    {
        @Override
        public void onClick(final View view)
        {
            Log.d(APP_TAG, "add task click received");
 
            TodoActivity.this.provider.addTask(TodoActivity.this
                    .etNewTask
                    .getText()
                    .toString());
 
            TodoActivity.this.renderTodos();
        }
    };
 
    @Override
    protected void onStop()
    {
        super.onStop();
    }
 
    @Override
    protected void onStart()
    {
        super.onStart();
    }
 
    @Override
    public void onCreate(final Bundle bundle)
    {
        super.onCreate(bundle);
 
        this.setContentView(R.layout.main);
        this.provider = new TodoController(this);
        this.taskView = (ListView) this.findViewById(R.id.tasklist);
        this.btNewTask = (Button) this.findViewById(R.id.btNewTask);
        this.etNewTask = (EditText) this.findViewById(R.id.etNewTask);
        this.btNewTask.setOnClickListener(this.handleNewTaskEvent);
 
        this.renderTodos();
    }
 
    private void renderTodos()
    {
        final List<String> beans = this.provider.getTasks();
 
        Log.d(TodoActivity.APP_TAG, String.format("%d beans found", beans.size()));
 
        this.taskView.setAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,
                beans.toArray(new String[]
                        {})));
 
        this.taskView.setOnItemClickListener(new OnItemClickListener()
        {
            @Override
            public void onItemClick(final AdapterView<?> parent, final View view, final int 
position, final long id)
            {
                Log.d(TodoActivity.APP_TAG, String.format("item with id: %d and position: %d", id, 
position));
 
                final TextView v = (TextView) view;
                TodoActivity.this.provider.deleteTask(v.getText().toString());
                TodoActivity.this.renderTodos();
            }
        });
    }
}
The Controller
Shown in Listing 2-12, the controller binds the UI to the data but also creates a layer of separation 
between the model and view code above. This interface between the two layers provides a 
framework for the code to expand and for new developers to follow the MVC pattern to know what 
new code belongs where.
Listing 2-12.  MVC Controller code

public class TodoController {
    /*The Controller provides data from the Model for the View to bind to the UI.  */
     private TodoModel db_model;
    private List<String> tasks;
    public TodoController(Context app_context)
    {
        tasks = new ArrayList<String>();
        db_model = new TodoModel(app_context);
    }
    public void addTask(final String title)
    {
        final ContentValues data = new ContentValues();
        data.put("title", title);
        db_model.addEntry(data);
    }
    //Overrides to handle View specifics and keep Model straightforward.
    public void deleteTask(final String title)
    {
        db_model.deleteEntry("title='" + title + "'");
    }
    public void deleteTask(final long id)
    {
        db_model.deleteEntry("id='" + id + "'");
    }
    public void deleteAll()
    {
        db_model.deleteEntry(null);
    }
    public List<String> getTasks()
    {
        Cursor c = db_model.findAll();
        tasks.clear();
        if (c != null)
        {
            c.moveToFirst();
            while (c.isAfterLast() == false)
            {
                tasks.add(c.getString(0));
                c.moveToNext();
            }            
            c.close();
        }
        return tasks;
    }
}

The layout for the To Do List screen is defined in the Layout.xml file, It is also shown in Listing 2-3.
Listing 2-3.  Layout.xml
<?xml version="1.0" encoding="utf-8"?> (change to LinearLayout)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget31"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <TableRow
        android:id="@+id/row"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/tasklist"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/etNewTask"
            android:layout_width="200px"
            android:layout_height="wrap_content"
            android:text=""
            android:textSize="18sp" >
        </EditText>
 
        <Button
            android:id="@+id/btNewTask"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@+string/add_button_name" >
        </Button>
    </TableRow>
    <ListView
        android:id="@+id/tasklist"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >
    </ListView>
</RelativeLayout>

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

LinearLayout
    螢幕的最外層,只要定義元件皆以水平(horizontal)或垂直(vertical)排列。

元件的高度與寬度

Android的所有元件都具備兩個屬性,也就是元件的高與寬,屬性名稱為「layout:height」與「layout:width」,許多人直覺想要以螢幕的畫素為元件訂定個別的高度與寬度,其實,為元件訂定固定的高與寬是不適合的,因為Android手機產品非常多元,有的手機的解析度是480×720,有的是640×960、640×1136、1080×1920或甚至1440×2560,如此眾多的差異性。假設我們的APP訂的元件大小是固定的,那是無法滿足所有的螢幕需求的。因此,Android建議開發者在訂定元件大小時,若希望只占用元件內容資料時,使用「wrap_content」值,當想要元件占滿所在區域可用空間時,使用「match_parent」值,筆者使用上節的LinearLayout垂直配置的範例,說明如下。

符合元件內容物-wrap_content

       意義是元件只占可顯示其內容物的大小,代表元件的高與度都只占必要的空間

以元件所在的容器為主-match_parent

       意義是所在容器有多大就占多大

元件的間距-margin

每一個元件都可指定其上下左右與其他元件的距離,稱之為「Margin」間距,「android:layout_margin」為其屬性名稱,可以統一設定四個方向的間距,亦可個別設定。

元件的對齊

為元件設定「layout:gravity」屬性,可決定元件在容器中向那個方位靠攏

另一個與layout:gravity屬性很像的屬性為「gravity」,假如在一個版面中有很多個元件,想要每個元件都以同一種方式對齊,要一個個去設定實在太繁複了,「gravity」屬性提供給版面配置或容器統一設定裏面元件的對齊方式,只要設定版面即可。請到LinearLayout,設定gravity屬性, 例如所有在LinearLayout中的元件都要水平置中。

LinearLayout中的權重weight

當我們在LinearLayout中放入多個元件時,可利用屬性「weight」權重,為元件分配不同的權重值,其預設值為0。透過分別設定在LinearLayout內的元件的權值值,可依權重分配元件可以占用的空間,

例如: 三個Button元件的權重值都是1.0 ,將會平均分配空間

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
 
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="BUTTON1" />
 
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:text="BUTTON2" />
 
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:text="BUTTON3" />
</LinearLayout>
 

RelativeLayout

RelativeLayout是Android Studio在產生Activity時使用的預設Layout,在此版面的元件都需要參考一個對象,這個對象可以是任一個元件或是元件所在位置的元件,在本例也就是面版本身(parent),也可稱為元件所在容器。

       元件相對位置屬性有幾個常用的屬性,對象為父元件(容器)的相關屬性:
  • android:layout_alignParentTop:若為true,對齊所在容器的頂邊
  • android:layout_alignParentBottom:若為true,對齊所在容器的下緣
  • android:layout_alignParentLeft:若為true,對齊所在容器的左邊緣
  • android:layout_alignParentRight:若為true,對齊所在容器的右邊緣
  • android:layout_alignParentCenter:若為true,元件放在容器的中央

當對象為一般元件時的相關屬性:

  • android:layout_above:元件放在對象之上
  • android:layout_below:元件放在對象之下
  • android:layout_toLeftOf:元件的右邊緣對齊對象的左邊緣
  • android:layout_toRightOf:元件的左邊緣對齊對象的右邊緣
  • android:layout_alignTop:元件的上緣對齊對象的上緣
  • android:layout_alignBottom:元件的下緣對齊對象的下緣
  • android:layout_alignLeft:元件的左邊緣對齊對象的左邊緣
  • android:layout_alignRight:元件的右邊緣對齊對象的右邊緣
  • android:layout_centerHorizontal:元件水平置中
  • android:layout_centerVertical:元件垂直置中

 

 

文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

資料參考:https://alysivji.github.io/reactive-dashboards-with-dash.html (frameware,good)
Big Data Analytics with Pandas and SQLite in Python
https://datacarpentry.org/python-ecology-lesson/09-working-with-sql/index.html

https://sqlitebrowser.org/
https://medium.com/a-r-g-o/using-plotlys-dash-to-deliver-public-sector-decision-support-dashboards-ac863fa829fb (another porject)

 

Dash Application Design: MVC Pattern

Every Dash application could be divided into the following components:
(1)Data Manipulation - Perform operations to read / transform data for display
(2)Dashboard Layout - Visually render data into output representation
(3)Interaction Between Components - Convert user input to commands for data manipulation + render
When designing a Dash application, we should stucture our code into three sections:

1. Data Manipulation (Model)
2. Dashboard Layout (View)
3. Interaction Between Components (Controller)


We created the following template to help us get started:
 

Historical Match-up Dashboard

In this section, we will create a full-featured Dash application that can be used to view historical soccer data.

We will use the following process to create / modify Dash applications:

  1. Create/Update Layout - Figure out where components will be placed
  2. Map Interactions with Other Components - Specify interaction in callback decorators
  3. Wire in Data Model - Data manipulation to link interaction and render

Data is stored in an SQLite database:

Download the Dash application template file from above:

$ export DB_URI=sqlite:///soccer-stats.db
$ python app.py
* Running on http://0.0.0.0:8050/ (Press CTRL+C to quit)
* Restarting with stat

 


 

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

https://dash.plot.ly/  (user giude)
https://dash.plot.ly/?_ga=2.103650308.589841288.1542985557-762329219.1542985557
https://thingsmatic.com/2016/07/10/a-web-app-for-iot-data-visualization/
https://medium.com/@plotlygraphs/introducing-dash-5ecf7191b503
https://www.tutorialspoint.com/r/r_scatterplots.htm (R software)
http://www.math.nsysu.edu.tw/~lomn/homepage/R/R_plot.htm (R software)
https://alysivji.github.io/reactive-dashboards-with-dash.html (frameware,good)

 

You can check out the code yourself across a few repositories:

#-----------------------------------------

In order to start using Dash, we have to install several packages.

  1. The core dash backend.
  2. Dash front-end
  3. Dash HTML components
  4. Dash core components
  5. Plotly
(1) Install Dask (https://dash.plot.ly)
In your terminal, install several dash libraries. These libraries are under active development, 
so install and upgrade frequently. Python 2 and 3 are supported. 
sudo pip install dash  # The core dash backend
sudo pip install dash-html-components # HTML components
sudo pip install dash-core-components  # Supercharged components
sudo pip install dash-table  # Interactive DataTable component (new!)
sudo pip install plotly --upgrade
sudo pip install dash_table_experiments

(2) python HelloDash.py

(1) Hello.py

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash()
colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}
app.layout = html.Div(style={'backgroundColor': colors['background']}, children=[
    html.H1(
        children='Hello Dash',
        style={
            'textAlign': 'center',
            'color': colors['text']
        }
    ),
    html.Div(children='Dash: A web application framework for Python.', style={
        'textAlign': 'center',
        'color': colors['text']
    })
])
if __name__ == '__main__':
   app.run_server(debug=True,port=8080)

#------------------

(2)HelloDash.py

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),
    html.Div(children='''Dash: A web application framework for Python.'''),
    dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
                {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},

            ],
            'layout': {
                'title': 'Dash Data Visualization'
            }
        }
    )
 ])

if __name__ == '__main__':
   app.run_server(debug=True,port=8080')
 

最後一個份如何將DASH deploy to google cloud 

Deploying Dash to Google App Engine

 

 

 

 

 

 

stanley 發表在 痞客邦 留言(0) 人氣()

資料來源: Control of your Appliances and IoT Devices at your Fingertips with Flask
Connecting to your database
https://dzone.com/articles/restful-web-services-with-python-flask

 

E:xample : Browser Graphical User Interface (GUI) for Sprinkler System

undefined

 

undefined

TEST & Control the relay(s) for the Sprinkler system:
This python routine starts the vales connected to the Raspberry Pi pins with the numbers listed
​​​​​​​in the array “zone” (8, 7, 14, 15, 18, 23, 24, 25), 

# import the necessary packages
import RPi.GPIO as GPIO
import time

# set the GPIO mode
GPIO.setmode(GPIO.BCM)

zone = [8, 7, 10, 9, 14, 15, 18, 23, 24, 25]
#################################################
# List of zones with the times for each zone ####
#################################################
#8  = House front left, Large tree, at walk way
s8  = [zone[0], 200]
#7  = House front left, Large tree, at garage wall
s7  = [zone[1], 200]
#10 = right corner of backyard behind shed
s10 = [zone[2], 200]
#9  = Backyard cherry trees
s9  = [zone[3], 200]

#14 = Orange Trees, Plum trees, Apple tree..
s14 = [zone[4], 200]
#15 = Front right stripe
s15 = [zone[5], 200]
#18 = Cypresses left
s18 = [zone[6], 200]
#23 = planting boxes
s23 = [zone[7], 200]
#24 = Roses house wall
s24 = [zone[8], 150]
#25 = House wall at AC
s25 = [zone[9], 150]

def openCloseValves(valve, zeit):
        print("Opening Valve",valve," for ",zeit," seconds")
        time.sleep(5.0)
        GPIO.setup(valve, GPIO.OUT)
        GPIO.output(valve, GPIO.LOW)    # Open valve
        time.sleep(zeit)
        GPIO.output(valve, GPIO.HIGH)   # Close valve
        time.sleep(5.0)
        print("done...")

def run():
        openCloseValves(s8[0],s8[1])
        openCloseValves(s7[0],s7[1])
        openCloseValves(s10[0],s10[1])
        openCloseValves(s9[0],s9[1])

        openCloseValves(s14[0],s14[1])
        openCloseValves(s15[0],s15[1])
        openCloseValves(s18[0],s18[1])
        openCloseValves(s23[0],s23[1])
        openCloseValves(s24[0],s24[1])
        openCloseValves(s25[0],s25[1])

        # perform a bit of cleanup
        GPIO.cleanup()
        
if __name__=='__main__':
        try:
                run()
        except:
                # Shut all valves...
                for num in zone:
                        GPIO.setup(num, GPIO.OUT)
                        GPIO.output(num, GPIO.HIGH)
                GPIO.cleanup()
                print("An Error occured OR user stopped routine...!!!")
                raise

The file webForm contains following python code

1
sudo chmod ug+x webForm.py
$> ./webForm

settings.json 

{
    "0": [
        "25",
        "200"
    ],
    "1": [
        "27",
        "200"
    ],
    "2": [
        "21",
        "200"
    ],
    "3": [
        "23",
        "200"
    ]
}

 

sprinklerMain.py

import RPi.GPIO as GPIO
import time
import json
import os
from collections import OrderedDict 
 
def openCloseValves(valve, zeit):
    print("Opening Valve " + str(valve) + " for " + str(zeit) + " seconds..."),
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    time.sleep(5.0)
    GPIO.setup(valve, GPIO.OUT)
    GPIO.output(valve, GPIO.LOW)    # Open valve
    time.sleep(zeit)
    GPIO.output(valve, GPIO.HIGH)    # Close valve
    time.sleep(5.0)
    print("Done")
    
def openValve(valve):
    print("Opening Valve " + str(valve) + " ..."),
    #GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(valve, GPIO.OUT)
    GPIO.output(valve, GPIO.LOW)    # Open valve
    print("Done")
    return()
    
def closeValve(valve):
    print("Closing Valve " + str(valve) + " ..."),
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(valve, GPIO.OUT)
    GPIO.output(valve, GPIO.HIGH)    # Close valve
    print("Done")
    return()
    
def run():
    value =[]
    with open('/home/pi/flaskSprinkler/settings.json') as data_file:
        sprinkler = json.load(data_file)
        for i in range(0,len(sprinkler)):
            value = sprinkler[str(i)]
            valve = int(value[0])
            zeit = int(value[1])
            print("sprinkler new " + str(valve) + " value : " + str(zeit))
            openCloseValves(valve, zeit)
    # Perform a bit of cleanup...
    GPIO.cleanup()
    
def closeAllValves():
    GPIO.setmode(GPIO.BCM)
    for value in range(2,28):
        try:
            GPIO.setup(int(value), GPIO.OUT)
            GPIO.output(int(value), GPIO.HIGH)
        except:
            continue    # continue with the next GPIO pin...
    GPIO.cleanup()
 
        # Kill routine sprinkler script in case that is running...
        try:
                os.system("sudo pkill -9 sprinklerMain.py")
                time.sleep(1)
        except:
                pass
 
  
    
if __name__=="__main__":
    try:
        run()
    except:
        closeAllValves()
        print("An Error occured OR user stopped routine...!!!")
        raise

 

 

 guiPage.html. This file needs to be in the folder templates/.

<div class="container">
<h2>Sprinkler Setting Web Form</h2>
&nbsp;
 
<form action="" method="post">
<div class="form-group">
<table class="responsable">
<tbody>
<tr>
<td><label for="Z0">Zone 0 : Front left, at walk way</label></td>
<td><input id="Z0" class="form-control" name="Z0" type="text" placeholder="Front left, at walk way..." /></td>
<td><button style="width: 100px; font-size: 18pt; padding: 2px; border: 3px solid green;" name="submit" type="submit" value="start0">Start0</button></td>
<td><button style="width: 100px; font-size: 18pt; padding: 2px; border: 3px solid red;" name="submit" type="submit" value="stop0">Stop0</button></td>
</tr>
<tr>
<td><label for="Z1">Zone 1 : Front left, at garage wall</label></td>
<td><input id="Z1" class="form-control" name="Z1" type="text" placeholder="Front left, at garage wall..." /></td>
<td><button style="width: 100px; font-size: 18pt; padding: 2px; border: 3px solid green;" name="submit" type="submit" value="start1">Start1</button></td>
<td><button style="width: 100px; font-size: 18pt; padding: 2px; border: 3px solid red;" name="submit" type="submit" value="stop1">Stop1</button></td>
</tr>
<tr>
<td><label for="Z2">Zone 2 : Right backyard, behind shed</label></td>
<td><input id="Z2" class="form-control" name="Z2" type="text" placeholder="Right backyard, behind shed..." /></td>
<td><button style="width: 100px; font-size: 18pt; padding: 2px; border: 3px solid green;" name="submit" type="submit" value="start2">Start2</button></td>
<td><button style="width: 100px; font-size: 18pt; padding: 2px; border: 3px solid red;" name="submit" type="submit" value="stop2">Stop2</button></td>
</tr>
<tr>
<td><label for="Z3">Zone 3 : Backyard cherry trees.</label></td>
<td><input id="Z3" class="form-control" name="Z3" type="text" placeholder="Backyard cherry trees..." /></td>
<td><button style="width: 100px; font-size: 18pt; padding: 2px; border: 3px solid green;" name="submit" type="submit" value="start3">Start3</button></td>
<td><button style="width: 100px; font-size: 18pt; padding: 2px; border: 3px solid red;" name="submit" type="submit" value="stop3">Stop3</button></td>
</tr>
</tbody>
</table>
&nbsp;
 
</div>
<button class="btn btn-success" style="width: 650px; font-size: 18pt; padding: 2px; border: 6px solid black;" name="submit" type="submit" value="submitAll">Write times specified (let-out fileds not changed)</button> <button class="btn btn-success" style="width: 650px; font-size: 18pt; padding: 2px; border: 6px solid green;" name="submit" type="submit" value="startAll">Start all zones</button> <button class="btn btn-success" style="width: 650px; font-size: 18pt; padding: 2px; border: 6px solid red;" name="submit" type="submit" value="stopAll">Stop all zones</button>
<h3>Values Set:</h3>
</form></div>
&nbsp;

 

undefined

Keeping it Running

 

@reboot /home/pi/flaskSprinkler/shutSprinkler.py

15 22 * * * nohup /home/pi/flaskSprinkler/sprinklerMain.py &
*/5 * * * * nohup /home/pi/flaskSprinkler/isFlaskRunning.sh &

#----------------------

shutSprinkler.py

# import the necessary packages
import RPi.GPIO as GPIO
import time
#import cv2

# load the input image and display it to our screen
#print("click on the image and press any key to continue...")
#image = cv2.imread("hoover_dam.jpg")
#cv2.imshow("Image", image)
#cv2.waitKey(0)
#print("moving on...")

# set the GPIO mode
GPIO.setmode(GPIO.BCM)

# loop over the LEDs on the TrafficHat and light each one
# individually
for i in (14,15,18,23,24,25,8,7,2,3,4,17,27,22,10,9):
        GPIO.setup(i, GPIO.OUT)
        time.sleep(0.1)
        GPIO.output(i, GPIO.HIGH)

# perform a bit of cleanup
GPIO.cleanup()

isFlaskRunning.sh

laskRunning.sh
 
 
 
 
 
Default
1
2
3
4
5
6
7
#!/bin/bash
#!/bin/bash
 
service="webForm"
 
if ! ps -e | grep "$service" ; then
/home/pi/flaskSprinkler/webForm
fi
文章標籤

stanley 發表在 痞客邦 留言(0) 人氣()

Close

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

reload

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼