반응형

어플리케이션 구성시, named route 를 사용하면, 어플리케이션 구조를 좀더 단순화 할수 있습니다.
그러면 코드의 시인성( readability ) 도 좋아지겠죠?

app route를 사용 하는 방식도 여러가지가 있는데요.
그중에서 저는 아래와 같이 router를 따로 분리해서 사용하는 것을 선호 합니다.


app router의 page 구성


abstract class Routes{

  static const INITIAL = '/';
  static const DEVICE = '/device';
  static const MONITOR = '/monitor';
  static const SEARCH = '/search';
}


class AppPages {
  static final pages = [
    GetPage(
        name: Routes.INITIAL, page: () => const MainPage()),
    GetPage(
        name: Routes.DEVICE, page: () => const DeviceControlPage()),
    GetPage(
        name: Routes.MONITOR, page: () => const MonitorPage()),
    GetPage(
        name: Routes.SEARCH, page: () => const SearchPage()),
  ];
}
반응형

Windows 환경에서 flutter_blue 를 설치하려다 다음과 같은 에러가 발생했습니다.

 


\macos\Classes\FlutterBluePlugin.h' (OS Error: The client does not have the required privileges.

 

이 문제는 flutter_blue 가 설치 될때 , symbolic link ( soft link) 로 되어있는 파일을 접근 하려다 발생되는 에러 입니다.

linux , macos 의 경우에는 symbolic link가 실제 file처럼 접근이 가능하지만, windows에서는 단순 숏컷으로 동장하기 때문에 문제가 발생한것으로 보이는데요.

해결하기 위해서는 flutter_blue 배포자가 수정을 해줘야 하겠지만,우리는 임시로 해결법을 찾아야 합니다.


아래 과정을 통해서 임시로 해결할 수 있습니다.

 

 

Solution 2: It is working well. (I'm using this solution)

 

1. flutter_blue의 git 을 clone 또는 download 합니다. (https://github.com/pauldemarco/flutter_blue)

2. 다운받은 flutter_blue 을 [설치된 flutter sdk folder]\flutter\.pub-cache\hosted 폴더로 복사합니다.

3. 이름을 변경합니다.  flutter_blue -> flutter_blue-0.8.0

 

이렇게 해서 pub get을 다시 해보시면 잘 동작 할것입니다.

.pub_cache\hosted 가 cache 폴더로 plugin들을 설치할떄 여기에 cache를 남겨두기 떄문에 여기에 정상적으로 업데이트 해놓으면 pub get 동작이 정상적으로 동작합니다.

 

 

반응형

\macos\Classes\FlutterBluePlugin.h' (OS Error: The client does not have the required privileges.



Problem: flutter_blue has installation problem in windows.

 

 

Solution 2: It is working well. (I'm using this solution)

 

1. download flutter_blue from git (https://github.com/pauldemarco/flutter_blue)

2. move flutter_blue to [your flutter sdk folder]\flutter\.pub-cache\hosted folder.

3. change name flutter_blue -> flutter_blue-0.8.0

4. done

 

 

 

 


Solution 1: it's just first found out solution. unfortunately it just can avoid ONLY get pub error.(FAILED)
1. flutter pub get

==> error will be occurred.

[your flutter sdk folder]\flutter\.pub-cache\_temp\dir7d36fb45\macos\Classes\FlutterBluePlugin.h' (OS Error: 지정된 파일을 찾을 수 없습니다.
, errno = 2)

2. copy dir7d36fb45 to [your flutter sdk folder]\flutter\.pub-cache\hosted\pub.dartlang.org
3. change name dir7d36fb45 to flutter_blue-0.8.0
4. cd flutter_blue-0.8.0 (created by you)
5. create pubspec.yaml in flutter_blue-0.8.0 folder
6. fill below content in pubspec.yaml

name: flutter_blue
description:
  Flutter plugin for connecting and communicating with Bluetooth Low Energy devices,
  on Android and iOS
version: 0.8.0
homepage: https://github.com/pauldemarco/flutter_blue

environment:
  sdk: '>=2.12.0 <3.0.0'
  flutter: ">=1.12.13+hotfix.6"

dependencies:
  flutter:
    sdk: flutter
  convert: ^3.0.0
  protobuf: ^2.0.0
  rxdart: ^0.26.0
  collection: ^1.15.0
  meta: ^1.3.0

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  plugin:
    platforms:
      android:
        package: com.pauldemarco.flutter_blue
        pluginClass: FlutterBluePlugin
      ios:
        pluginClass: FlutterBluePlugin
      macos:
        pluginClass: FlutterBluePlugin

7. now you have done preparing flutter_blue  cache :)
8. lets do  flutter pub get   !!
maybe it will be worked.
I know it is a temporary solution. but I believe it will help you understand how to work pub get..

If you need new pubspec.yaml ,
you can find out in here : https://github.com/pauldemarco/flutter_blue/blob/master/pubspec.yaml

반응형

Old wifi manager apis are deprecated from android framework.

 

only it can be controlled startLocalOnyHotsopt, by guide document , this api can enable wifi hotspot but cannot use wireless network.

it means wifi hotspot is not controlled anymore by application.

 

startLocalOnlyHotspot

 

 

https://stackoverflow.com/questions/6394599/android-turn-on-off-wifi-hotspot-programmatically

 

 

 

Android turn On/Off WiFi HotSpot programmatically

Is there an API to turn On/Off the WiFi HotSpot on Android programmatically? What methods should I call to turn it On/Off? UPDATE:There's this option to have the HotSpot enabled, and just turn On...

stackoverflow.com

 

 

반응형

Dart 의 비동기/동기(async/ sync programming) 표현 방법은 상당히 직관적이면서도 편리한 부분들이 많습니다.

효율적인 동작을 위한 코딩을 하려다 보면 필연적으로 async로 코드 작성이 필요로 하게 되죠.

 

아래 간단한 주제를 가지고 한번 얘기 해보고자 합니다.

 

A라는 데이타 목록을 가지고 B라는 과정을 거쳐서 C라는 결과를 도출하고 D라는 데이타 목록으로 저장을 하려고 합니다.
1. A의 각 항목들은 B라는 과정을 거칠때 1~2 초 정도 시간이 걸린다. 
2. B 과정을 입력 A 데이타에 따라 처리 시간이 달라진다.(1초 또는 2초)
3. D에 저장 되는 순서는 A의 순서와 같아야 한다.

일단 A항목들을 순차적으로 처리하게 되면, A의 개수만큼 시간이 늘어나게 됩니다.

따라서 비동기(async)프로그래밍를 고려하게 될 것입니다.

 

위의 상황에 대해서 코딩을 해보면,  가장먼저 다음과 같이 생각해볼 수 있을 것입니다.

A = srcData, B =Future.delayed() , C =  A와 같은 type , D = dstData 라고 합시다.

import 'dart:async';
import 'dart:math';


List<String> srcData=[];
List<String> dstData=[];

init(){
  for( int i = 0;i<24; i++ ){
    srcData.add('mmm_${i}');
  }
}

Future copyToDst(int i){// test를 위해서 1~2초의 랜덤 수행 순서로, src에서 dstData 에 copy 하는 내용.
  return Future.delayed(Duration(seconds: Random().nextInt(2)),(){
    dstData.add(srcData[i]);
    print('src[$i]=>dst');
  });
}



fillDest() async{
  init();
  print("fillDest: length=${srcData.length}");
  for(int s = 0; s<srcData.length ;s++){
    copyToDst(s);
  }
}

void main() async{
 await fillDest();
 await Future.delayed(Duration(seconds: 5));
 print(dstData);
  
}

1초 또는 2초에 처리가 완료 되면, dstData에 저장을 하게 됩니다.

실행 결과는 아래와 같습니다.

기본적인 동작은 하는것 처럼 보입니다.

 

<실행 결과>

fillDest: length=24
src[3]=>dst
src[4]=>dst
src[5]=>dst
src[8]=>dst
src[10]=>dst
src[11]=>dst
src[15]=>dst
src[16]=>dst
src[20]=>dst
src[21]=>dst
src[22]=>dst
src[0]=>dst
src[1]=>dst
src[2]=>dst
src[6]=>dst
src[7]=>dst
src[9]=>dst
src[12]=>dst
src[13]=>dst
src[14]=>dst
src[17]=>dst
src[18]=>dst
src[19]=>dst
src[23]=>dst
[mmm_3, mmm_4, mmm_5, mmm_8, mmm_10, mmm_11, mmm_15, mmm_16, mmm_20, mmm_21, mmm_22, mmm_0, mmm_1, mmm_2, mmm_6, mmm_7, mmm_9, mmm_12, mmm_13, mmm_14, mmm_17, mmm_18, mmm_19, mmm_23]

 

음... 그런데  결과에서 보듯이 "mmm_숫자" 결과의 순서가 srcData의 순서와 맞지 않는 것을 볼수 있습니다.

 

이제 여기서 몇가지 고민을 하게 되겠죠? 가령 "어떻게 순서를 맞출 것인가? " 와 같은 것 말이죠.

대략 한 3가지 방법을 생각해 볼 수 있을것 같네요..

 

첫번째,  copyToDest를  await 으로 처리하는 방법입니다.

  for(int s = 0; s<srcData.length ;s++){
    await copyToDst(s);
  }

 직접 실행해보면, .. 으악... 이런 최악의 수네요..ㅠ_ㅠ 실행시간이 너무 오래걸려요.

 

 

두번째,  map을 이용하는 방법이 있겠네요. 

map을 이용해서 srcData의 순서를 map의  index로 사용하는 방법이죠.

import 'dart:async';
import 'dart:math';


List<String> srcData=[];
Map<int, String> dstData={};

init(){
  for( int i = 0;i<24; i++ ){
    srcData.add('mmm_${i}');
  }
}

Future copyToDst(int i){// test를 위해서 1~2초의 랜덤 수행 순서로, src에서 dstData 에 copy 하는 내용.
  return Future.delayed(Duration(seconds: Random().nextInt(2)),(){
    dstData[i] = srcData[i];
    print('src[$i]=>dst');
  });
}



fillDest() async{
  init();
  print("fillDest: length=${srcData.length}");
  for(int s = 0; s<srcData.length ;s++){
     copyToDst(s);
  }
}

void main() async{
 await fillDest();
 await Future.delayed(Duration(seconds: 5));
 print(dstData);
  
}

 

<실행결과>

fillDest: length=24
src[0]=>dst
src[1]=>dst
src[2]=>dst
src[3]=>dst
src[5]=>dst
src[6]=>dst
src[7]=>dst
src[11]=>dst
src[12]=>dst
src[16]=>dst
src[18]=>dst
src[21]=>dst
src[22]=>dst
src[4]=>dst
src[8]=>dst
src[9]=>dst
src[10]=>dst
src[13]=>dst
src[14]=>dst
src[15]=>dst
src[17]=>dst
src[19]=>dst
src[20]=>dst
src[23]=>dst
{0: mmm_0, 1: mmm_1, 2: mmm_2, 3: mmm_3, 5: mmm_5, 6: mmm_6, 7: mmm_7, 11: mmm_11, 12: mmm_12, 16: mmm_16, 18: mmm_18, 21: mmm_21, 22: mmm_22, 4: mmm_4, 8: mmm_8, 9: mmm_9, 10: mmm_10, 13: mmm_13, 14: mmm_14, 15: mmm_15, 17: mmm_17, 19: mmm_19, 20: mmm_20, 23: mmm_23}

실행결과를 보시면 데이타의 순서는 처리속도에 따라 순서가 달라졌지만, 우리는 map의 index를 사용할 수 있기 때문에 index 순서로 결과를 뽑아볼수 있습니다. ^^ 매우 좋은 결과네요. 

속도도 거의 차이가 없고, 결과도 좋고요.

한가지 걸리는 것은 , dstData를 얻기까지 1~2초가 걸리는데, data가 정상적으로 들어왔는지, 언제 사용해야 하는지가 약간은 애매하네요.

 

 

 

세번째, dstData를 Future List로 변경하는 방법인데요. 

dstData 의 형태를 List<String> 에서 List<Future<String>> 변경하고 copyToDst의 형태도 dstData에 Future<String>을 추가하도록 변경되었습니다.

이렇게 하면 dstData 에는 실행 결과가 들어가는 것이 아니라 실행 명령 순서인 Future<String> 을 저장하는 것을 의도 합니다.

import 'dart:async';
import 'dart:math';


List<String> srcData=[];
List<Future<String>> dstData=[];

init(){
  for( int i = 0;i<24; i++ ){
    srcData.add('mmm_${i}');
  }
}


Future copyToDst2(int i)async{// test를 위해서 1~2초의 랜덤 수행 순서로, src에서 dstData 에 copy 하는 내용.
  return dstData.add(Future<String>.delayed(Duration(seconds: Random().nextInt(2)),(){
    print('src[$i]=>dst');
    return srcData[i];
  }));
}


fillDest() async{
  init();
  print("fillDest: length=${srcData.length}");
  for(int s = 0; s<srcData.length ;s++){
    copyToDst2(s);
  }
}

void main() async{
 await fillDest();
 await Future.delayed(Duration(seconds: 5));
  
  
 List<String> l=[];
 for (var d in dstData){
   l.add(await d);
 }
  
  
 print(l);
  
}

 

추후 Future<String>의 결과를 얻기 위해서는 await dstData[i] 형태로 사용하면 String을 얻어올 수 있게 됩니다.

 

<실행 결과>

fillDest: length=24
src[0]=>dst
src[1]=>dst
src[2]=>dst
src[3]=>dst
src[5]=>dst
src[6]=>dst
src[7]=>dst
src[10]=>dst
src[11]=>dst
src[12]=>dst
src[16]=>dst
src[20]=>dst
src[23]=>dst
src[4]=>dst
src[8]=>dst
src[9]=>dst
src[13]=>dst
src[14]=>dst
src[15]=>dst
src[17]=>dst
src[18]=>dst
src[19]=>dst
src[21]=>dst
src[22]=>dst
[mmm_0, mmm_1, mmm_2, mmm_3, mmm_4, mmm_5, mmm_6, mmm_7, mmm_8, mmm_9, mmm_10, mmm_11, mmm_12, mmm_13, mmm_14, mmm_15, mmm_16, mmm_17, mmm_18, mmm_19, mmm_20, mmm_21, mmm_22, mmm_23]

 

 

추가로, 

map을 사용했을때 " dstData 언제 사용해야 하는지가 약간은 애매하네요." 라고 했던 부분에 대해서 추가로 생각해보자면,

List<Future<String>> 을 사용했던것 처럼, map<int , Future<String>> 으로 사용하게 되면, 필요한 데이타를 사용할때 await을 활용하여 data 결과가 채워지기를 기다릴 수 있겠는데요 ? 

 

아무튼 async 프로그래밍을 다루기에 편리한 언어인 dart 인데 이를 활용 안할 이유가 없을것 같죠? 그렇죠?

 

다들 dart의  async, async* sync, sync* 에 대해서 찾아보시고 알아두시면 즐거운 코딩 생활에 도움이 될것 같습니다.

 

 

반응형

1. MediaPipe

https://developers.google.com/mediapipe

 

MediaPipe  |  Google for Developers

An open source, cross-platform, customizable ML solution for live and streaming media.

developers.google.com

On Device AI 를 쉽게 구현하고 다양한 서비스를 만들수 있는 프래임워크입니다.

 

MediaPipe 솔루션은 애플리케이션에 인공 지능(AI) 및 기계 학습(ML) 기술을 신속하게 적용할 수 있는 라이브러리 및 도구 모음을 제공합니다. 이러한 솔루션을 애플리케이션에 즉시 연결하고 필요에 맞게 사용자 정의하며 여러 개발 플랫폼에서 사용할 수 있습니다. MediaPipe 솔루션은 MediaPipe 오픈 소스 프로젝트 의 일부 이므로 애플리케이션 요구 사항에 맞게 솔루션 코드를 추가로 사용자 정의할 수 있습니다. 

 

 

 

 

 

 

 

 

미디어파이프의 데모를 확인해볼 수 있는 좋은 예제가 될 것 같아 링크를 해놓습니다.

 

 

https://makernambo.com/155?category=774191 

반응형

Python 에서 package는 folder를 의미합니다.

package 정의하는 방법에 대해서 얘기 하고자 합니다.

아시는 분도 있을 거지만,  간단한 py file만 만들어보다가 여러 py 를 묶어서 library 형태로 배포하는 방법입니다.

 

 

1. folder를 만든다.  (폴더 이름은 아무거나 영문 소문자로 사용)

   => 예로 mylib 라고 하겠습니다.

2. 내 py file들을 (class 로 구성한파일)을 mylib으로 옮긴다.

  => 예) bike.py , man.py

#bike.py
class Bike :
    def run(self):
        print("moved 1000 m")
        
        
#man.py
class Man :
    def run(self):
        print("moved 100 m")

3. __init__.py 를 mylib 안에 만든다.

 

4. __init__.py 에 다음과 같이 class 를 import 하는 코드를 넣어준다.

 

from .bike import Bike  
# . 현재 폴더 에서 bike 파일에서 Bike class를 불러옴.
from .man import Man

 

5. 이제 my lib을 사용합니다.

 

from mylib import *


b = Bike()
b.run()

m = Man()
m.run()

'python' 카테고리의 다른 글

파이선 스터디  (0) 2018.04.05
반응형

DevOps 란 ?

인터넷 서비스는 서비스 개선을 빠르게 부담 없이 적용 하는것이 매우 중요합니다.

사실 이 부분은 인터넷 서비스 뿐만 아니라, 거의 모든 소프트웨어 분야에서 요구되는 사항이긴 하죠. 

빠르고 완벽하게 되면 뭐든 좋은거니까요. ^o^

 

서비스만 놓고 얘기해보자면, 아래와 같이 몇가지 단계로 구분 해볼 수 있을 것이에요.

기획 -> 개발 -> 테스트 -> 배포 -> 운영

 

DevOps 라는 개념은 이 과정을 단순화 하고 쉽게 할 수 있도록 하는 것인데요, 말 그대로 개발(Dev) 과 운영(Operation)즉,  개발된 S/W를 빠르게 배포하고 운영을 하는 것입니다.

 

DevOps라는 명칭이 사용하게 된 것도 이런 개념을 담은 솔루션들이 나왔기 때문이겠죠....

 

 

관련해서 읽어볼 꺼리들을 링크로 공유 합니다.

 

https://jjeongil.tistory.com/854

 

DevOps : 관련 도구 : 종류, 소개

위 그림은 DevOps 수명 주기 전반의 도구 사슬을 표현하였습니다. 도구 사슬의 의미는 각 영역이 별개가 아니라 도구 간 연계를 통해서 시너지를 이룬다는 측면을 강조한 것입니다. 각 영역별로

jjeongil.tistory.com

 

 

https://tech.ktcloud.com/19

 

협업 프로젝트 관리 1부 - 오픈소스 툴 소개

 개인 vs 팀의 프로젝트 관리 어느 날, 친구에게 교통사고를 당했다는 연락을 받은 나 (다급)괜찮아? 안다쳤어? vs (침착) 보험 들었어? 여러분은 어떻게 반응하시나요? 1000% J형이라 대학생 때부터

tech.ktcloud.com

 

+ Recent posts