반응형

다원 WIFI 스마트 플러그를 사용자 컴포넌트 만들어 주신분이 있어서 Home Assistant 에서 직접 사용이 가능 했었는데

나름(?) 보안 패치를 했는지 사용이 막힌지 꽤 오래 되었다.

그냥 저냥 smart things 와 home assistant 를 연결해서 썼는데 이건 전력량 모니터링, 전력량에 따른 동작 등등 다양한 활용 방법이 막혀있다.

 

찾아보니 벌써 해결책이 나와 있다.

저작권을 위해 링크만 걸겠다.

 

방법은 초기화 후 서버로 연결을 안시키고 집에서 만들어놓은 mqtt 서버에 연결시키는 방법이다.

 

cafe.naver.com/koreassistant/1977

 

다원 WIFI 스마트 플러그 (B530-WF/B540-WF) 로컬 등록 (이것도 너프해보시지)

대한민국 모임의 시작, 네이버 카페

cafe.naver.com

 

부족한 내용을 조금 설명하자면

모델명 400 은 일단 안되었다. 뭐가 다른지 모르겠는데 안되니까 슬프게도..

 

그리고 hass.io 에서 add-on 으로 mqtt borker 를 사용중이면 간단하게 config를 사용중일텐데,,

플러그 한개당 한개씩 아이디가 필요해서 사용자 추가 어떻게 해야 하나 고민된다.

그런데 그냥 사용자/비번을 여러줄 넣어주면 된다.  (아래 스샷처럼)

 

 

이제 요녀석을 이용해서 여러가지 활용이 가능하다. 전력 모니터링, 과부하시 종료, 한개 켜면 다른 스위치 자동으로 켜고 끄기 등등..

 

반응형
반응형

앱을 간단하게 버그를 고치고 다시 올렸는데 이번에는 이상하게 한방에 통과를 안시켜주더라.

 

AppTrackingTransparency 문제 발생

요런 문제가 있다고 한다.

 

바이너리가 거부됨

2020년 11월 7일

If your app integrates AppTrackingTransparency, please indicate where in your app we can find the AppTrackingTransparency permission


Guideline 2.1 - Information Needed



We're looking forward to completing the review of your app, but we need more information to continue. Specifically, we noticed that your app uses the AppTrackingTransparency framework, but we haven't been able to locate the relevant AppTrackingTransparency permission requests.

While it is not required to implement AppTrackingTransparency at this time, we check to make sure the implementation is compliant with our guidelines when we detect the framework in an app.

Next Steps

If your app integrates AppTrackingTransparency, please indicate where in your app we can find the AppTrackingTransparency permission request.

If your app does not integrate AppTrackingTransparency, please indicate this information in the Review Notes section for each version of your app in App Store Connect when submitting for review.

Resources
See the app privacy question update.
Learn more about how AppTrackingTransparency protects user's privacy and data.

 

AppTrackingTransparency Pemission requests 를 넣은 기억이 없어서 다시 검색해봤다. 

 

AppTrackingTransparency Pemission requests란? 

iOS 14 부터는 앱에 포함된 광고 등에서 타겟팅 광고를 위한 디바이스 구분을 위한 식별값 IDFA를 사용해도 되는지 사용자에게 묻는 동의다. 딱 한번 요청을 받을 수 있다. 앱에 구현할 경우 아래와 같이 보인다.

이때 사용자가 직접 수정할 수 있는 문구는 저기 빨간 동그라미 안쪽 문구 뿐이다.

자세한 정보는 Prepare for iOS 14+ 에서 확인 가능하다. 

Flutter 에서는 어떻게 설정하나?

사용하는 패키지에 따라 해당 설정이 필요한 경우가 있는데, 내 경우에는 admob_flutter 플러그인 적용 중 포함되었다.

ios/Runner/info.plist  파일을 열어서 아래와 같이 추가되어있을 경우 해당 프레임워크가 포함된다고 한다.

	<key>NSUserTrackingUsageDescription</key>
	<string>This identifier will be used to deliver personalized ads to you.</string>

 

앱 심사는 어떻게??

일단 적용된 스크린샷과 위치를 알려주는 답장을 쓰고 기다리고 있다.

과연 어떻게 될런지?? 

 

-> 하루 뒤 Pass! 

반응형
반응형

앱을 처음부터 끝까지 모두 만들 수 없다.

기본적인 도구나 구조들은 인터넷을 찾아보면 공개된 내용도 많다.

 

특히 flutter 는 pub.dev에 공개된 플러그인들이 매우 많다. 여기서 잘 검색하고 like 가 많고 score가 높은 패키지를 쓰면 버그가 상대적으로 적고 만족도가 높을 것이다.

pub.dev

 

Dart packages

Pub is the package manager for the Dart programming language, containing reusable libraries & packages for Flutter, AngularDart, and general Dart programs.

pub.dev

 

이번에 우리가 필요로 하는 패키지를 정리하면 아래와 같다.

필요한 패키지(플러그인)들은 pubspec.yaml 파일을 열어서 dependencies 추가해준 후 Pub get 버튼으로 모두 사용 가능하게 해주자. 나중에 플러그인이 너무 많이 업데이트 되서 사용 못할 수 있으니 버전을 같이 써주자.

dependencies:
  flutter:
    sdk: flutter
  share: ^0.6.5+4
  device_info: ^0.4.2+9
  admob_flutter: ^1.0.1
  advertising_id: ^1.0.0 

요렇게 만들어서 사용할 예정이다.

 

 

그리고 device_info 예제를 그대로 긁어다가 main.dart 에 붙여넣고 실행해보자.

첫 실행은 매우 오래걸리니(1~10분) 안된다고 너무 걱정하지 말자.

잠시 다른 생각을 하다보면 뜬다.

// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'dart:async';

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:device_info/device_info.dart';

void main() {
  runZoned(() {
    runApp(MyApp());
  }, onError: (dynamic error, dynamic stack) {
    print(error);
    print(stack);
  });
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  static final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
  Map<String, dynamic> _deviceData = <String, dynamic>{};

  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  Future<void> initPlatformState() async {
    Map<String, dynamic> deviceData;

    try {
      if (Platform.isAndroid) {
        deviceData = _readAndroidBuildData(await deviceInfoPlugin.androidInfo);
      } else if (Platform.isIOS) {
        deviceData = _readIosDeviceInfo(await deviceInfoPlugin.iosInfo);
      }
    } on PlatformException {
      deviceData = <String, dynamic>{
        'Error:': 'Failed to get platform version.'
      };
    }

    if (!mounted) return;

    setState(() {
      _deviceData = deviceData;
    });
  }

  Map<String, dynamic> _readAndroidBuildData(AndroidDeviceInfo build) {
    return <String, dynamic>{
      'version.securityPatch': build.version.securityPatch,
      'version.sdkInt': build.version.sdkInt,
      'version.release': build.version.release,
      'version.previewSdkInt': build.version.previewSdkInt,
      'version.incremental': build.version.incremental,
      'version.codename': build.version.codename,
      'version.baseOS': build.version.baseOS,
      'board': build.board,
      'bootloader': build.bootloader,
      'brand': build.brand,
      'device': build.device,
      'display': build.display,
      'fingerprint': build.fingerprint,
      'hardware': build.hardware,
      'host': build.host,
      'id': build.id,
      'manufacturer': build.manufacturer,
      'model': build.model,
      'product': build.product,
      'supported32BitAbis': build.supported32BitAbis,
      'supported64BitAbis': build.supported64BitAbis,
      'supportedAbis': build.supportedAbis,
      'tags': build.tags,
      'type': build.type,
      'isPhysicalDevice': build.isPhysicalDevice,
      'androidId': build.androidId,
      'systemFeatures': build.systemFeatures,
    };
  }

  Map<String, dynamic> _readIosDeviceInfo(IosDeviceInfo data) {
    return <String, dynamic>{
      'name': data.name,
      'systemName': data.systemName,
      'systemVersion': data.systemVersion,
      'model': data.model,
      'localizedModel': data.localizedModel,
      'identifierForVendor': data.identifierForVendor,
      'isPhysicalDevice': data.isPhysicalDevice,
      'utsname.sysname:': data.utsname.sysname,
      'utsname.nodename:': data.utsname.nodename,
      'utsname.release:': data.utsname.release,
      'utsname.version:': data.utsname.version,
      'utsname.machine:': data.utsname.machine,
    };
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text(
              Platform.isAndroid ? 'Android Device Info' : 'iOS Device Info'),
        ),
        body: ListView(
          children: _deviceData.keys.map((String property) {
            return Row(
              children: <Widget>[
                Container(
                  padding: const EdgeInsets.all(10.0),
                  child: Text(
                    property,
                    style: const TextStyle(
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                Expanded(
                    child: Container(
                  padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
                  child: Text(
                    '${_deviceData[property]}',
                    maxLines: 10,
                    overflow: TextOverflow.ellipsis,
                  ),
                )),
              ],
            );
          }).toList(),
        ),
      ),
    );
  }
}

 

이렇게 기본적인 화면이 뜬다.

이 화면을 예쁘게 만들고 admob 을 추가해주고 올리면 되겠지?

 

이번엔 여기까지,,, 

 

 

반응형

'Flutter 프로그래밍' 카테고리의 다른 글

안드로이드 앱 만들기(1) - 준비 과정  (0) 2020.10.31
반응형

간단한 Device ID를 보여주는 앱을 만들어보자.

앱을 만들고 Play store colsol에 등록하는 과정까지 진행해보자.

 

 

준비

먼저 안드로이드 스튜디오를 설치한다.

developer.android.com/studio/install?hl=ko

 

Android 스튜디오 설치  |  Android 개발자  |  Android Developers

Windows, macOS 또는 Linux에서 Android 스튜디오를 설정 및 설치합니다.

developer.android.com

flutter SDK 도 설치해준다. 폴더는 알아서..

flutter-ko.dev/docs/get-started/install

 

설치

Flutter를 설치할 운영 체제를 선택해주세요:{{site.alert.note}} **Are you on Chrome OS?** If so, see the official [Chrome OS Flutter installation docs!](/docs/get-started/install/chromeos){{site.alert.end}}

flutter-ko.dev

설치 후 환경변수 설정도 해준다. 시작메뉴에서 '환경 변수' 로 검색해서 진입 후 환경변수 설정도 해준다.

그리고 안드로이드 스튜디오에서 setting -> Plugins -> Marketplace 에서 flutter 플러그인을 설치한다. dart 도 같이 설치된다.

셋팅에서 SDK 를 검색해서 필요한 sdk를 다운받고

sdk-tool도 필요한것 받자.

android SDK build-tool 과 Android Emulator와 Android SDK Platform-Tools 는 꼭 필요하다.

기타 필요한 것들도 받으면 된다.

 

 

안드로이드 폰과 adb 연결을 위해 케이블로 연결하거나 에뮬레이터에 적당한 녀석을 받아서 실행해놓자.

오른쪽 위에 AVD Manager에 들어가서 Create Virtual.... 어쩌고를 누르고 phone 에서 적당한 녀석으로 받자.

픽셀로 가면 최신폰, 넥서스로 가면 구형폰이다.

 

 

 

 

이제 File -> New -> New Flutter Project 를 누르고

(프로젝트 시작 전이면 File 선택을 안할수도 있다... 셋팅에 따라 다름)

Flutter Application 을 누른다.

아래처럼 대충 프로젝트 이름을 넣어준다. 

 

여기서 pakage name 을 넣어줘야 하는데 이건 플레이 스토어에 올릴 때 유일한 이름이 되어야 한다.

보통 웹사이트 주소 역순으로 넣는식으로 많이 한다.

qsurf.tistroy.com  이 내가 가진 도메인이면 com.tistory.qsurf.device_info_app 이런식으로 만들면 겹칠 확률이 매우 낮다.

 

 

 

그럼 이제 간단한 예제가 들어있는 플러터 앱이 만들어졌다.

shift+F10 을 누르거나 메뉴에서 잘 찾아서 run을 누르면 아래와 같이 + 를 누르면 숫자가 올라가는 앱이 실행된다.

여기서 아이폰용 애뮬레이터는 맥에서만 사용 가능하다.

 

오늘은 여기까지

반응형
반응형

구글 admob 을 적용시켜서 테스트를 하다 보면

Failed to load ad: 0 라는 메세지를 받게 된다.

 

원인은 안드로이드/iOS 폰에서 직접 테스트 할 때 정식으로 배포된 앱이 아닌 경우 광고를 불러오지 못해서다.

이때 test로 사용할 장치 device id 를 admob 에 미리 넣어놓으면 해당 id를 가진 장치에서는 test ad가 뜬다.

 

 

Java / Kotlin

device id 를 얻는 방법은 java 와 kotlin 관련 문서가 많다.

 

해당 장치에서 앱을 실행하고 logCat 에서 adRequest 를 검색해보면 아래처럼 나온다고 한다. 여기서 보이는 Device ID를 복사해서 쓰면 된다.

 

 12-29 11:18:25.615: I/Ads(2132): To get test ads on this device, call adRequest.addTestDevice("D9XXXXXXXXXXXXXXXXXXXXXXXXXXXXX");".

 

 

 

Flutter

 

Flutter / 안드로이드 스튜디오 사용중인데 logCat 에서 잘 안보여서 다른 방법을 찾아봤다.

device_id 를 얻어오는 많은 plugin 이 있는데 그중 하나를 골라서 사용하면 된다.

 

아래 plugin을 사용해봤다.

 

 

 

플러그인 설치

패키지를 pubspec.yaml 파일에 넣어주고 pubget 을 해준다.

dependencies:
  device_id: ^0.2.0

 

사용을 원하는 파일에 import 

import 'package:device_id/device_id.dart';

 

예제 코드

아래와 같이 DeviceId.getID 로 deviceID를 얻어와서 사용하면 된다.

import 'package:flutter/material.dart';
import 'package:device_id/device_id.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String deviceID;

  void getDeviceID() async {
    String deviceId = await DeviceId.getID;
    deviceID = 'Device ID is $deviceId';
    print('Device ID is $deviceId');
  }

  @override
  Widget build(BuildContext context) {
    getDeviceID();
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text('$deviceID'),
        ),
      ),
    );
  }
}

 

반응형
반응형

안드로이드 / iOS 앱을 만들다보면 여러가지 권한을 사용해야 할 때가 있다.

카메라, 저장장치, 위치정보, 메세지, 연락처 등등 여러 정보를 기기에서 받아서 활용하는 경우가 많다.

 

만약 적절한 권한이 없는 경우 디버그 모드에서는 동작하는데 컴파일 후 장치에서 실행하면 오류와 함께 종료되는 경우가 많다.

 

다행히도 flutter 에 적절한 패키지가 있다. 패키지가 있을 경우에는 정말 사용하기 편하다.

 

Permission Handler 5.0.1+1

현시점에서 버전은 5.0.1+1 이다. 

pub.dev/packages/permission_handler

 

permission_handler | Flutter Package

Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.

pub.dev

 

사용전 설정

안드로이드 

  • pre 1.12 android project 로 업그레이드 후 사용
  • gladdle.properties 파일에 아래와 같이 추가
android.useAndroidX=true
android.enableJetifier=true
  • 'android/app/build.gradle' 파일에서 android sdk 버전 29로 설정
android {
  compileSdkVersion 28
  ...
}

 

iOS

Info.plist 에 권한 추가

아래 링크에서 모든 종류의 권한 예시 확인 가능

github.com/Baseflow/flutter-permission-handler/blob/develop/permission_handler/example/ios/Runner/Info.plist

 

 

사용법

pubspec.yaml 파일 depency 에 추가해준다.

  permission_handler: ^5.0.1+1

사용하려는 dart 파일에 import 추가 후 사용

import 'package:permission_handler/permission_handler.dart';

 

권한 상태 확인(및 종류)

권한 상태는 undetermined, granted, denied, restricted 가 있으며 안드로이드는 추가로 permanentlyDenied 가 있다.

예를 들어 카메라 권한 상태가 궁금하면 Permission.camera.status 로 확인하면 된다.

var status = await Permission.camera.status;
if (status.isUndetermined) {
  // We didn't ask for permission yet.
}

// You can can also directly ask the permission about its status.
if (await Permission.location.isRestricted) {
  // The OS restricts access, for example because of parental controls.
}

 

권한 요청

아래와 같이 Permission.contacts.request() 로 요청하면 된다. 

return 값은 undetermined, granted, denied, restricted 와 같은 값이다.

if (await Permission.contacts.request().isGranted) {
  // Either the permission was already granted before or the user just granted it.
}

// You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
  Permission.location,
  Permission.storage,
].request();
print(statuses[Permission.location]);

 

 

사용예시

실제로 사용할 때는 await 가 있기 때문에 async 로 감싸진 클래스(또는 함수) 에서 다뤄야 한다.

위젯 생명주기중 하나인 initState 에서는 Future 클래스가 호출이 안된다. 

이럴때는 WidgetsBinding.instance.addPostFrameCallback((_) { 요기 }  에다가 넣어주면 된다.

 

아래와 같은 함수를 만들어놓고 불러오면 된다.

여기서 카메라 권한 확인용으로 만든 camPermissionIsGranted 변수를 사용했다.

처음엔 false 로 사용 불가능으로 해놓고 권한이 확인되면 true 로 변경하자.

 

bool camPermissionsGranted = false;

Future<bool> CamPermissionIsGranted() async {
  var _status = await Permission.camera.status.isGranted;
  camPermissionsGranted = _status;
  return _status;
}

 

 

권한이 있을때와 없을때 widget 을 어떻게 구현하는지가 처음에 햇갈렸다.

FutureBuilder로 구현해봤는데 뭔가 배보다 배꼽이 큰거같아서 다시 검색해보니 더 쉽고 깔끔한 방법이 있다.

 

예를들어 Scaffold의 body 에 구현한다고 하면 아래 ? : 연산자를 쓰면 쉽다.

그리고 권한 확인이 되면 camPermissionIsGranted 의 값을 바꾸고 동시에 setState로 위젯을 다시 build 하면 된다.

(조건) ? (true인 경우 실행) : (false인 경우 실행) 

return Scaffold(
  body: camPermissionsGranted 
          ? Container(child: 퍼미션 있을경우 실행)
          : Container(child: 퍼미션 없을 경우 실행)

 

아래 예제 맨 아랫줄에서 보면 setState까지 구현된 권한 요청 함수를 볼 수 있다.

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

void main() => runApp(MyApp());

/// Example Flutter Application demonstrating the functionality of the
/// Permission Handler plugin.
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
          actions: <Widget>[
            IconButton(
              icon: const Icon(Icons.settings),
              onPressed: () async {
                var hasOpened = openAppSettings();
                debugPrint('App Settings opened: ' + hasOpened.toString());
              },
            )
          ],
        ),
        body: Center(
          child: ListView(
              children: Permission.values
                  .where((Permission permission) {
                    if (Platform.isIOS) {
                      return permission != Permission.unknown &&
                          permission != Permission.sms &&
                          //permission != Permission.storage &&
                          permission != Permission.ignoreBatteryOptimizations &&
                          permission != Permission.accessMediaLocation;
                    } else {
                      return permission != Permission.unknown &&
                          permission != Permission.mediaLibrary &&
                          permission != Permission.photos &&
                          permission != Permission.reminders;
                    }
                  })
                  .map((permission) => PermissionWidget(permission))
                  .toList()),
        ),
      ),
    );
  }
}

/// Permission widget which displays a permission and allows users to request
/// the permissions.
class PermissionWidget extends StatefulWidget {
  /// Constructs a [PermissionWidget] for the supplied [Permission].
  const PermissionWidget(this._permission);

  final Permission _permission;

  @override
  _PermissionState createState() => _PermissionState(_permission);
}

class _PermissionState extends State<PermissionWidget> {
  _PermissionState(this._permission);

  final Permission _permission;
  PermissionStatus _permissionStatus = PermissionStatus.undetermined;

  @override
  void initState() {
    super.initState();

    _listenForPermissionStatus();
  }

  void _listenForPermissionStatus() async {
    final status = await _permission.status;
    setState(() => _permissionStatus = status);
  }

  Color getPermissionColor() {
    switch (_permissionStatus) {
      case PermissionStatus.denied:
        return Colors.red;
      case PermissionStatus.granted:
        return Colors.green;
      default:
        return Colors.grey;
    }
  }

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(_permission.toString()),
      subtitle: Text(
        _permissionStatus.toString(),
        style: TextStyle(color: getPermissionColor()),
      ),
      trailing: IconButton(
          icon: const Icon(Icons.info),
          onPressed: () {
            checkServiceStatus(context, _permission);
          }),
      onTap: () {
        requestPermission(_permission);
      },
    );
  }

  void checkServiceStatus(BuildContext context, Permission permission) async {
    Scaffold.of(context).showSnackBar(SnackBar(
      content: Text((await permission.status).toString()),
    ));
  }

  Future<void> requestPermission(Permission permission) async {
    final status = await permission.request();

    setState(() {
      print(status);
      _permissionStatus = status;
      print(_permissionStatus);
    });
  }
}

 

 

추가로 안드로이드의 경우 권한 수락을 완전히 거부할 경우 있는데 그럴때는 앱정보에 들어가서 직접 권한을 줘야 한다.

아래 루틴을 requestPermission 에 넣어주면 좋다.

if (await Permission.speech.isPermanentlyDenied) {
  // 유저가 완전히 권한을 거부하였을 경우 앱설정으로 진입
  // 유저가 알아보기 쉽게 도움말을 띄우면 더 좋음
  openAppSettings();
}

 

이상 끝.

반응형
반응형

 하루에 한번이상 꼭 가게 되는 화장실이다. 들어갈 때 향기로웠으면 좋겠지만 항상 물을 사용하는 장소라서 습기로 가득차 있어서 향기는 커녕 곰팡이 피지 않게 관리하는 것도 쉽지 않다.

 환풍기를 하루종일 켜놓으면 조금 나을 텐데 그렇다고 하루종일 켜놓는건 전기세도 아깝고 시끄럽고 잘못하면 환풍기에서 전기 화재가 날 수 도 있는거 아닌가? 불안한 마음이 한가득이다.

 

 그래서 IoT로 꾸며볼까 했는데, 아서라 화장실은 IoT 에서 나름 중간보스 이상급이다. 사람이 들고 나고 카운팅 하는것도 쉽지 않고 화장실에 있는지 없는지 확인하기도 쉽지 않다.

 

타임렉

 가장 쉬운 방법으로 환풍기 스위치를 끄면 약 5분 또는 10분정도 더 돌다가 꺼지도록 해주는 손쉬운 제품이 있다고 해서 설치해봤다.

 이름은 '위너스 타임랙' 이며 스위치를 뜯어서 저 두개만 끼워 넣으면 된다.

 

https://coupa.ng/bLnXdL

 

위너스 조명 환풍기 겸용 시간지연 모듈 타임랙

COUPANG

www.coupang.com

 

 행복하게 주문하고 배송이 온 후 설치했다.

 스위치 박스를 힘줘서 대충 뜯어내고 (일자 드라이버나 비슷한거로 아래쪽 홈에 걸쳐서 뜯어내면 됨) 나사를 풀고 설치완료.

작업중이라 공통선이 빠져있다. 암튼 설명서 보고 연결하면 됨
설명서 이미지 나는 오른쪽 타입

 

 어 그런데 스위치가 토글 스위치다. 환풍기를 내가 정말로 끈건지 아니면 타임랙이 동작하는지 구분할 수 없다...

 너무 슬픈 현실에 다시 스위치를 샀다. 나는 소비형 인간인가.

 

르그랑 엑셀

클래식한 엑셀 스위치

 사진은 정말 못찍었는데 블링블링하면서 레트로한 엑셀 스위치다. 진짜 호주에서 수입해오는 제품. 엄청 튼튼하고 한국형이 아니라 귀찮다. 심지어 고정 나사가 저 제품에 쓰기에는 짧아서 나사도 따로 샀다. 제품 설명서에 나온 연결 방법도 잘못되서 힘들었다. 1번과 2번에 각자 선을 꽃아야 한다. 스위치에 따라 1,2 가 연결되었다 끊어졌다 한다. G 인가 하는 단자는 아에 안쓰는 단자...

 

https://coupa.ng/bLnYms

 

르그랑 엑셀 / 3구스위치 / 블랙

COUPANG

www.coupang.com

 

 어쨋거나 이번에도 눈꼽만큼 집안 살림살이 업그레이드 완료!

 

 

이 게시물은 “파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음"

반응형
반응형

블루투스가 없는 PC에서 블루투스 이어폰이나 키보드를 사용하기 위해서 블루투스 동글을 구할때가 있습니다.

이때 확인해야 하는 사양을 알려드립니다.

USB 동글

 


안정성과 성능이 가장 중요해?

 

먼저 결론부터 말하자면 PCI-e 카드로 설치하는게 가장 좋은 성능을 보입니다.

수신율과 거리 안정성 모두 USB 동글과 비교할 수 없는 수준입니다.

 

물론 bluetooth만 지원하는 카드보다 wifi와 bluetooth 동시에 지원하는 카드가 더 많습니다.

가격대 성능도 나쁘지 않지요.

 

국내 사이트에서 구입할 수도 있습니다. 아래 제품은 m2 슬롯에 연결하는 제품이네요.

https://coupa.ng/bLm3lM

 

인텔 AX200 NGW 기가비트 무선 랜카드 Desktop kit

COUPANG

www.coupang.com

 

저렴하게 알리 익스플레스에서 구매할 수도 있지요. 

https://ko.aliexpress.com/item/4000809241696.html?aff_platform=true&aff_short_key=8hBHvxE&isdl=y&src=danawa

 

US $8.35 35% OFF|데스크탑 와이파이 6 PCI E 무선 어댑터 2.4Gbps 2.4G/5Ghz 1/802 ac/ax 블루투스 5.0 AX200NGW 와�

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com

 


간편하게 USB 타입 ? 

여러종류의 동글들이 있는데 칩셋 종류가 중요합니다. 그리고 프로그램 설치를 따로 할 필요 없는 퀄컴이나 브로드컴 칩셋을 사용한 제품이 좋습니다.

  • 티피링크 UB400 - 퀄컴 칩셋
    장점 : Win10 드라이버 설치 필요 없음

https://coupa.ng/bLm3Es

 

티피링크 블루투스 4.0 나노 USB 어댑터 UB400

COUPANG

www.coupang.com

 

  • 퓨전FNC BU-4096 - 브로드컴 칩셋
    장점 : 호환성이 좋다는 평이 있음
    단점 : Win10 드라이버 설치 필요

https://coupa.ng/bLm3NH

 

퓨전에프엔씨 BU-4096 블루투스 동글 (USB)

COUPANG

www.coupang.com

 

 


USB동글인데 먼거리에서 쓰고 싶어요

먼 거리에서 쓰고싶으면 bluetooth class1 이 적용된 제품을 써야 합니다.

국내에서는 최근에는 판매가 되지 않아 직구를 해야 합니다.

예를 들면 아래와 같은 제품이 있습니다.

https://ko.aliexpress.com/item/32701426269.html?spm=a2g0o.productlist.0.0.1e524b93Iavhcs&algo_pvid=ebddfde0-2ae7-441a-a228-7005c001a7ad&algo_expid=ebddfde0-2ae7-441a-a228-7005c001a7ad-4&btsid=0be3743b15978384598584903eb358&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_

 

US $29.99 |Avantree Leaf Class 1 장거리 USB 블루투스 오디오 송신기 어댑터 (PC 노트북 용) Ma c PS 4 N intendo

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com


오디오 전용 동글

오디오 퀄리티가 중요하거나 레이턴시가 중요할때는 전용 동글이 따로 있습니다.

CREATIVE BT-W3 라는 제품인데요 블루투스 프로파일을 가장 여러종류를 지원하고 있으며

원하는 프로파일을 선택해서 연결 할 수 있거든요.

https://coupa.ng/bLm349

 

크리에이티브 Creative BT-W3 블루투스 V5.0 동글 (정품) 당일발송

COUPANG

www.coupang.com

 

 

즐거운 무선 라이프를 즐기세요~

 

 

 

본 게시글은 쿠팡 파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있습니다.

반응형

+ Recent posts