Search results for '전체'

  1. 2016.04.04 -- [FMX] 앱에서 문장을 출력하는 3가지 방법
  2. 2016.03.31 -- [안드로이드/iOS] 이미 배포(Deployment)된 파일 업데이트 하기
  3. 2016.03.07 -- [VCL] 다른 프로세스의 폼을 패널등에 넣기 (1)
  4. 2016.02.29 -- RAD Studio IDE에서 SVN 사용하기 + TortoiseSVN 사용하기
  5. 2016.02.29 -- SVN 서버 설치하기 - Visual SVN 이용
  6. 2016.02.25 -- 런타임 오브젝트 인스펙터(ObjectDebugger) 오픈소스 소개
  7. 2016.02.17 -- 애플 WWDR 인증서 만료로 iOS 개발자 인증서 이슈 해결 방안
  8. 2016.02.15 -- RAD Studio 2016년 로드맵
  9. 2016.02.05 -- [FireDAC MergeDataSet] 여러 데이터셋을 병합해 하나의 데이터셋을 구성할 수 있습니다.
  10. 2016.01.28 -- 델파이 iOS Touch ID 구현하기(래퍼 클래스) (1)
  11. 2016.01.14 -- [교육] 미니프로젝트과정 - 자료
  12. 2016.01.06 -- [팁] 온라인상에서 바이러스를 진단 하세요. - 구글 Virus Total
  13. 2015.11.16 -- [마이그레이션][팁] 유니코드 검토 대상 분석 도구
  14. 2015.11.09 -- [마이그레이션] 유니코드 적용시 검토할 사항들
  15. 2015.11.04 -- [데이터스냅] 데이터스냅 클라이언트에서 TCP/IP로 접속 시 ConnectTimeout이 적용되지 않는 경우 대처방법 (1)
  16. 2015.10.02 -- [따라하기] 건강데이터 수집 및 기록 시스템 #1 - BLE 기반 스마트 체중계에서 실시간 데이터 받기 (11)
  17. 2015.10.01 -- iOS9의 새로운 기능인 "App transport Security" 예외 허용을 위한 Info.plist xml 수정방법
  18. 2015.09.22 -- [교육] 사물인터넷 교육 (3)
  19. 2015.09.09 -- [교육] 한국감정평가협회 데이터스냅 교육 (2)
  20. 2015.09.07 -- [시애틀] 안드로이드 서비스 앱을 만들 수 있습니다.

[FMX] 앱에서 문장을 출력하는 3가지 방법

2016.04.04 11:22

앱에서 긴 글을 표시해야 하는 경우 3가지 방법을 이용해 표현할 수 있습니다.(아래 방법외에도 더 많은 방법이 있을 수 있습니다.)



TextContents.zip


1, TMemo 이용

문장을 나타내는 대표적인 컴포넌트입니다. 문장 출력뿐아니라 입력도 받을 수 있습니다.

출력이 목적인 경우 ReadOnly 속성을 True로 설정하면 입력을 제한합니다.

자동 줄바꿈이 필요하면 TextSettings.WordWrap 속성을 True로 설정합니다.


2, TWebBrowser + HTML 이용

HTML을 표현하는 웹브라우저에 문장을 출력하는 방법입니다. HTML 태그를 이용해 글자크기, 색상, 스타일 등을 자유롭게 사용할 수 있습니다. 만약, 문장이 HTML로 구성된 경우 아주 좋은 선택 입니다.
웹브라우저에 HTML을 불러오려면 아래와 같이 LoadFromString 메소드를 이용합니다.
  WebBrowser1.LoadFromStrings(html, '');

3, TVertScrollBox + TText 이용

수직으로만 스크롤되는 스크롤박스(TVerScrollBox)에 텍스트(TText)를 추가해 문장을 표현하는 방법입니다.

여러개의 텍스트를 추가하면 글자크기, 색상, 스타일을 다르게 지정할 수 있습니다.

텍스트를 상단에 정렬(Align := Top)하면 추가된 순서대로 위에서부터 표시되며, AutoSize 속성을 True로 설정해 높이를 자동 조정할 수 있습니다.

아래 코드는 몇가지 속성을 설정해 동적(코드작성)으로 텍스트를 추가하는 코드 입니다.

procedure TForm1.Button2Click(Sender: TObject);
  procedure AddText(const AText: string; AFontSize: Integer = 12; AFontColor: TAlphaColor = TAlphaColorRec.Black);
  var
    Text: TText;
  begin
    Text := TText.Create(Self);
    Text.Parent := VertScrollBox1;
    Text.Align := TAlignLayout.Top;
    Text.TextSettings.HorzAlign := TTextAlign.Leading;
    Text.TextSettings.Font.Size := AFontSize;
    Text.TextSettings.FontColor := AFontColor;
    Text.AutoSize := True;
    Text.Text := AText;
  end;

var
  S: string;
begin
  AddText('제목1', 20);
  S := 'SVN 서버 소프트웨어는 소스코드 ......';
  S := S + '예를들어, 팀내에서 소스코드를 ......';
  S := S + '만약, 외부와 협업이 필요한 경우 ......';
  AddText(S);

  AddText('제목2', 15, TAlphaColorRec.Red);

  S := 'SVN 서버 소프트웨어는 오픈 소프트웨어 부터 상용 소프트웨어까지 다양하게 선택할 수 있습니다.';
  S := S + '아래 링크를 참고해 원하는 플랫폼과 원하는 SVN 서버 소프트웨어를 설치할 수 있습니다.';
  AddText(S);
end;

추가로, 

델파이 마크다운 라이브러리를 이용할 수 있습니다. 다음 링크를 확인하세요.

http://blog.hjf.pe.kr/428

험프리.김현수 파이어몽키

[안드로이드/iOS] 이미 배포(Deployment)된 파일 업데이트 하기

2016.03.31 11:06

사운드, 이미지, 텍스트 파일을 최초배포하고, 변경된 파일을 다시 배포할 경우 덮어쓰기(overwrite)가 되지않는 이슈가 있습니다.(10 시애틀. 2016년 3월) 해당 증상은 안드로이드와 iOS 모두 해당됩니다.

해당 이슈는 파일을 배포하는 System.StartUpCopy.pas에 구현된 내용을 살펴보니 배포 대상파일이 있는 경우(FileExist) 배포를 진행하지 않도록 구현되어 있습니다.


위 이슈를 해결하는 방법은 3가지 정도로 생각해볼 수 있습니다.

1, System.StartUpCopy.pas를 수정하는 방법

2, 업데이트할 파일을 새로운 이름으로 배포하고, 앱 시작시 기존 파일로 덮어쓰는 방법

3, 파일을 앱과 함께 최초 배포 후, 파일 변경이 필요할 경우 인터넷 등을 통해 자동 업데이트 하는 방법


1, System.StartUpCopy.pas를 수정하는 방법

http://qc.embarcadero.com/wc/qcmain.aspx?d=125481 링크를 방문해 Xavier Dufaure de Citres 글을 참고해 수정할 수 있습니다.

Xavier Dufaure de Citres at 12/14/2014 3:10:58 PM -
Here is a workaround on Android:
* modify System.StartUpCopy
   - in the interface section add "Var ASSET_OVERWRITE : Boolean = false;"
   - in the interface section exopose "procedure CopyStartUpFiles;"
   - in the CopyAssetToFile change "if (not FileExists(DestFileName)) then" by "if (not FileExists(DestFileName)) or ASSET_OVERWRITE then"

* in your own code, store in the preference file the last version the user ran. If the current version is newer do
  if optLastVersionRan<Version then
  Begin
    ASSET_OVERWRITE := true;
    CopyStartUpFiles;
    ASSET_OVERWRITE := false;
  End;

On the 1st installation the data will be copied twice (no biggy), on update the file will be overwritten.

Note for iOS: i find out that deploying the files i need in ".\Data\" is much better: it put the file directly in the bundle, this way the file are not archived (i got my app rejected because i had 12 Mb of data that was archived). Of course these files can only be read only.


2, 업데이트할 파일을 새로운 이름으로 배포하고, 앱 시작시 기존 파일로 덮어쓰는 방법 

배포파일이 업데이트 되면 새로운 파일명으로 배포 후 앱 시작 시 원래파일로 덮어쓰는 방식입니다.

위 이미지와 같이, "deploy.txt" 파일 배포 시 remote name을 "deploy_2.txt"로 배포했습니다.


프로젝트에는 아래와 같은 코드를 구현했습니다.(코드에 대한 설명은 생략합니다.)

uses
  System.IOUtils;

procedure TForm1.Button1Click(Sender: TObject);
var
  Path: string;
begin
  Path := TPath.Combine(TPath.GetDocumentsPath, 'deploy.txt');
  Memo1.Lines.LoadFromFile(Path);
end;

procedure TForm1.DeployFileUpdate(const AFilename, AUpdateFilename: string);
var
  OrgPath, UptPath: string;
begin
  OrgPath := TPath.Combine(TPath.GetDocumentsPath, AFilename);
  UptPath := TPath.Combine(TPath.GetDocumentsPath, AUpdateFilename);

  if TFile.Exists(UptPath) then
  begin
    if TFile.Exists(OrgPath) then
      TFIle.Delete(OrgPath);
    TFile.Move(UptPath, OrgPath);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DeployFileUpdate('deploy.txt',  'deploy_2.txt');
//  DeployFileUpdate('sound1.wav',  'sound1_2.wav');
//  DeployFileUpdate('env.ini',     'env_2.ini');
end;


3, 파일을 앱과 함께 최초 배포 후, 파일 변경이 필요할 경우 인터넷 등을 통해 자동 업데이트 하는 방법

배포파일 자동 업데이트는 파일별 버전관리가 필요하며, 업데이트 파일을 내려주는 서버가 필요합니다.

앱 실행 시 배포파일 버전을  서버에서 확인 후 업데이트할 파일이 있으면, Http, FTP 등으로 파일을 다운로드해 배포파일을 교채하는 방식입니다.

웹상의 파일을 다운로드 받는 방법은 아래 링크를 참고할 수 있습니다.

참고링크


  • 모바일(iOS, Android)에서 사용자 파일 배포 및 사용 : http://blog.hjf.pe.kr/104



험프리.김현수 파이어몽키

[VCL] 다른 프로세스의 폼을 패널등에 넣기

2016.03.07 15:52

프로세스를 생성하고 프로세스의 폼을 내 애플리케이션의 특정 영역(패널 등)에 넣도록 하는 코드입니다.


1, 아래 그림과 같이 메모장(notepad.exe)을 실행해 Panel에 넣어봤습니다. 

2, 프로세스의 폼(메모장)의 테두리를 없앴습니다.

3, 창 크기가 변경될때 프로세스의 폼 크기를 변경하도록 했습니다.(비동기)


EmbedFormSource.zip


uses
  Winapi.ShellAPI;

// 메모장 실행 / Embed  시키기
procedure TForm1.Button1Click(Sender: TObject);
var
  ExecuteFile : string;
  SEInfo: TShellExecuteInfo;
  RetryCount: Integer;
begin
  ExecuteFile:='c:\Windows\notepad.exe';

  FillChar(SEInfo, SizeOf(SEInfo), 0) ;
  SEInfo.cbSize := SizeOf(TShellExecuteInfo) ;
  with SEInfo do
  begin
    fMask := SEE_MASK_NOCLOSEPROCESS;
    Wnd := Panel1.Handle;
    lpFile := PChar(ExecuteFile) ;
    nShow := SW_HIDE;
  end;
  if ShellExecuteEx(@SEInfo) then
  begin
    // 실행 후 바로 찾을 수 없어 윈도우 핸들 찾기 재시도
    RetryCount := 0;
    repeat
      FAppWnd := FindWindow(PChar('notepad'), PChar('제목 없음 - 메모장'));
      Sleep(100);
      Inc(RetryCount);
    until (FAppWnd <> 0) or (RetryCount > 10);

    // 부모설정, 테두리제거, 최대화
    if FAppWnd <> 0 then
    begin
      WinAPI.Windows.SetParent(FAppWnd, SEInfo.Wnd);
      SetWindowLong(FAppWnd, GWL_STYLE,
              GetWindowLong(Handle, GWL_STYLE)  // 기존 스타일에서
          and not WS_BORDER                     // 크기조정 테두리 - 제거
          and not WS_THICKFRAME                 // 두꺼운 프레임 - 제거
          and not WS_DLGFRAME                   // 이중 테두리 - 제거
      );
      ShowWindow(FAppWnd, SW_SHOWMAXIMIZED);
    end;
  end;
end;

// 메모장 닫기(프로세스 종료)
procedure TForm1.Button2Click(Sender: TObject);
begin
  if FAppWnd <> 0 then
  begin
    PostMessage(FAppWnd, WM_Close, 0, 0);
    FAppWnd := 0;
  end;
end;

// 메모장 크기 조절
procedure TForm1.Panel1Resize(Sender: TObject);
begin
  if IsWindow(FAppWnd) then
    SetWindowPos(FAppWnd, 0, 0, 0, Panel1.Width, Panel1.Height, SWP_ASYNCWINDOWPOS);
end;


참고링크



험프리.김현수 Delphi/C++Builder

  1. 정말 감사합니다. 올바른 사용법을 찾았네요

    ActionList가 dll폼에서 제대로 작동하지 않아 exe를 패널안에 만들어 넣어보려고 하던중이었습니다.

RAD Studio IDE에서 SVN 사용하기 + TortoiseSVN 사용하기

2016.02.29 16:26

소스코드 버전관리 시스템으로 SVN을 사용하기 위해 SVN 서버 소프트트웨어를 서버에, 사용자 PC에 SVN 클라이언트 소프트웨어를 설치해야 합니다. 


이 글에서는 RAD Studio IDE에 내장된 SVN 클라이언트 플러그인을 이용해 SVN 서버 저장소에 파일을 등록(Import)하고 변경내역을 가져오고(Update), 작업내용을 저장(Commit)하는 내용을 설명합니다.

(RAD Studio에는 SVN, Git, Mercurial 3가지 버전관리 클라이언트 기능을 제공합니다.)


RAD Studio에 내장된 SVN 클라이언트 플러그인

SVN 저장소를 준비합니다.(만약, SVN 저장소가 없다면 다음 글을 참고해 SVN 서버 설치 후 저장소를 추가합니다. - http://blog.hjf.pe.kr/417)


SVN 저장소에 추가하기 - Add to Version Control(SVN: Import)

작성중인  소스코드를 SVN 서버의 중앙 저장소에 저장합니다. 이후 프로젝트 파일을 열고 소스코드를 변경 하구 중앙저장소에 반영(Commit)할 수 있습니다.
  1. 새로운 프로젝트를 추가(또는 작업 중인 프로젝트 열기) 합니다.
  2. 프로젝트 매니저에서 프로젝트를 우측 마우스 클릭 후 "Add to Version Control" 메뉴를 선택합니다.
  3. 버전관리 시스템 중 Subversion을 선택 합니다.
  4. Import 팬이 표시됩니다.
  5. URL of repository: 우측의 [...] 버튼을 누릅니다.
  6. SVN 저장소 주소를 입력 후 [Load] 버튼을 눌러 저장소와 연결합니다.
  7. 좌측 트리에서 저장할 디렉토리를 선택 후 [OK] 버튼을 누릅니다.
  8. [Import] 버튼을 눌러 서버 저장소에 저장합니다.

RAD Studio 10 시애틀에서 테스트 중 중앙저장소에 연결된 프로젝트에 프로젝트를 추가한 경우 [Import] 버튼이 비활성화 되는 현상이 발생했습니다.

이 경우 별도의 TortoiseSVN 등의 클라이언트 프로그램을 이용해 Import 작업을 진행하면 Commit / Upate 등의 작업을 IDE에서 이어서 진행할 수 있습니다.

SVN 저장소의 소스코드 가져오기 - Open From Version Control(SVN: Check out)

SVN 서버의 중앙저장소에 저장된  소스코드를 가져와 편집 후 작업내용을 중앙저장소에 저장할 수 있습니다.

  1. RAD Studio IDE에서 모든 파일을 닫습니다.
  2. File > Open From Version Control... 메뉴를 선택합니다.
  3. 버전관리 시스템 중 Subversion을 선택합니다.
  4. 저장소 경로(URL of Repository)와 저장할 로컬 경로(Destination)를 입력 후 [OK] 버튼을 클릭합니다.
  5. 다운로드 작업이 진행되며 완료 후 프로젝트를 선택해 열수 있습니다.

저장소에 작업내용 적용하기 / 중앙저장소 변경내역 가져오기 - Commit / Update

SVN 서버의 중앙저장소와 연결된 프로젝트는 작업내용(변경된 내용)을 중앙저장소에 적용하는 커밋(Commit)과 다른 사용자가 변경한 변경내역을 가져오는 Update 작업을 수행할 수 있습니다.

  1. SVN 서버의 저장소와 연결된 프로젝트를 엽니다.
  2. 프로젝트 매니저에서 우측 마우스 클릭 후 Subversion > Commit 메뉴를 선택합니다.
  3. Commit 팬이 표시됩니다.
  4. 중앙저장소에 저장할 파일을 선택(체크박스 선택)합니다.
  5. 변경한 작업에 대한 설명을 다른 사용자가 알아볼 수 있도록 작성합니다.
  6. [Commit] 버튼을 눌러 중앙저장소에 반영합니다.
  7. 프로젝트 매니저에서 우측 마우스 클릭 후 Subversion > Update 메뉴를 선택해 중앙저장소의 변경된 내역을 받아옵니다.

기타 더 많은 기능을 엠바카데로 기술문서를 참고해서 익힐 수 있습니다.

SVN 클라이언트 프로그램 이용

RAD Studio IDE에서 SVN을 제공하지 않는 버전을 사용한다면 별도로 SVN 클라이언트 프로그램을 설치해서 RAD Studio 소스코드를 버전관리 할 수 있습니다.

아래 링크를 참고해 원하는 플랫폼과 원하는 SVN 소프트웨어를 설치할 수 있습니다.

그 중 TortoiseSVN의 경우 윈도우의 기본 탐색기 팝업메뉴를 이용해 SVN 클라이언트 기능을 활용할 수 있습니다.



Tortoise SVN 사용법은 아래 링크들에서 자세히 확인해보시기 바랍니다.


관련자료

험프리.김현수 Delphi/C++Builder

SVN 서버 설치하기 - Visual SVN 이용

2016.02.29 14:40

소스코드 버전관리 시스템으로 SVN을 사용하기 위해 SVN 서버 소프트트웨어를 서버에, 사용자 PC에 SVN 클라이언트 소프트웨어를 설치해야 합니다.


이 글에서는 SVN 서버 소프트웨어를 서버에 설치하는 내용을 설명합니다.


SVN 서버 소프트웨어는 소스코드 버전관리 해야하는 작업자들이 접속할 수 있는 서버 머신에 설치해야 합니다.

예를들어, 팀내에서 소스코드를 버전관리 해야하는 경우 팀내에서 운영 중인 사내의 팀서버에 설치하는 것이 좋습니다.

만약, 외부와 협업이 필요한 경우 IDC 등에 SVN 서버 소프트웨어를 설치하면 외부 인원과도 소스코드 버전관리 할 수 있습니다.


SVN 서버 소프트웨어

SVN 서버 소프트웨어는 오픈 소프트웨어 부터 상용 소프트웨어까지 다양하게 선택할 수 있습니다.

아래 링크를 참고해 원하는 플랫폼과 원하는 SVN 서버 소프트웨어를 설치할 수 있습니다.

❑ Visual SVN 설치

저는 윈도우에서 손쉽게 설치 및 사용할 수 있는 Visual SVN Server을 설치했습니다.

라이선스

Visual SVN Server는 기능에 따라 Standard와 Enterprise로 구분되며 Standard는 회사에서도 무료로 설치(Avaliable for commercial use)할 수 있습니다.

설치

본인의 환경에 따라 32 bit 또는 64 bit 설치 파일을 받아 설치 파일 실행 후 안내에 따라 설치 합니다.

설치가 완료되면 시작 메뉴에서 "VisualSVN Server Mnager"를 찾아 실행하면 아래 화면이 표시됩니다.

❑ 저장소 및 사용자 생성

SVN  서버로 사용하기 위해서는 소스코드 저장소  생성과 사용자를 추가해야 합니다.(이 작업은 지정된 관리자가 하게 됩니다.)

저장소 생성

소스코드 버전관리가 필요한 프로젝트 또는 서비스 별로 저장소를 생성합니다.

왼편 트리메뉴에서 Repositories 항목  선택 후 오른쪽 팬에서 우측 마우스 버튼을 이용해 저장소를 생성(Create New Repository...)합니다.


저장소 유형, 저장소 이름, 저장소 구조를 선택합니다.

접근권한(접근 권한은 사용자 추가 후 다시 조정합니다.) 확인 후 저장소 생성을 마칩니다.


사용자 추가

왼쪽 트리메뉴에서 Users 메뉴 선택 후 오른쪽 팬에서 사용자를 추가(Create user)합니다.


저장소의 속성(Properties) 창의 Security 탭에서 접근 권한을 사용자 별로 조정합니다.

기타 참고사항

기타 추가적인 내용은 아래 링크를 참고해 확인하시기 바랍니다.

관련자료



험프리.김현수 Delphi/C++Builder

런타임 오브젝트 인스펙터(ObjectDebugger) 오픈소스 소개

2016.02.25 11:23

실행 시점에 폼, 컴포넌트의 속성과 이벤트, 데이터를 확인하고, 일부 속성을 변경할 수 있는 런타임 오브젝트 인스펙터(ObjectDebugger) 컴포넌트와 소스코드가 공개되었습니다. 해당 컴포넌트는 VCL 용입니다.

해당 컴포넌트의 소스코드는 런타임에서 동적으로 속성을 변경하는 기능 구현이 필요한 경우, RTTI 학습이 필요한 경우 참고하면 좋을 것 같습니다.






험프리.김현수 Delphi/C++Builder

애플 WWDR 인증서 만료로 iOS 개발자 인증서 이슈 해결 방안

2016.02.17 10:44

한국시간으로 2월 15일 오후 3시경 Apple Worldwide Developer Relations Certification Authority이 만료되었습니다.


그 여파로 잘 사용하던 iOS 인증서로 iOS Device 컴파일 시에 "[Error] Unable to match bundle identifier "앱이름" with AppID in all provisioning profiles" 오류가 발생 해 컴파일 되지 않았습니다.


그리고 키체인에서 개발자 인증서를 확인해보니, 인증서의 상태가 "이 인증서는 유효하지 않은 발급자를 가지고 있음" 이었습니다.


관련 이슈는 애플 개발자 포럼과 마르코칸투 블로그 등에서 다루고 있어 쉽게 해결할 수 있었습니다.


해결방안

  1. https://developer.apple.com/certificationauthority/AppleWWDRCA.cer 새로운 WWDRCA 인증서 다운로드(애플 iOS 개발자 계정 필요)
  2. 다운로드 받은 WWDRCA 인증서 더블클릭 해 설치
  3. 키 체인 실행
  4. 만료된 인증서 보기(보기 > 만료된 인증서 보기)
  5. 로그인과 시스템(좌측 키체인 메뉴에서 선택)에서 만료된 WWDRCA 삭제
  6. 각자 개발자 인증서 선택 후 "인증서가 유효함" 상태 확인(만약, 유효하지 않다면 시스템 재부팅 후 다시 확인)


험프리.김현수 기타정보

RAD Studio 2016년 로드맵

2016.02.15 18:33

2016년 Fire Monkey(불 원숭이)해가 밝았습니다. 마침 RAD Studio 2016년 로드맵이 공개되었습니다.

 - http://community.embarcadero.com/article/news/16211-embarcadero-rad-studio-2016-product-approach-and-roadmap-2


이번 로드맵에는 2개 트랙으로 구분해 제공합니다.


첫 번째 트랙은 코드 명 "Big Ben"으로 품질 및 첫 사용자 경험과 설치가 주요 주제입니다.(GetIt 기술을 이용해 새로 설치 시 유연하게 원하는 것만 선택 해 설치할 수 있고, 설치 시간을 줄였습니다.) 다음 기능들이 포함됩니다.

  • 분리되거나 합쳐지는 폼디자이너(VCL/FMX)
  • C++ 리팩토링
  • FireUI 앱 미리보기 - IDE의 폼디자이너를 모든 대상(데스크탑 및 모바일)에서 미리보기
  • FireMonkey 개선(윈도우, 맥과 모바일) - 주소록/연락처 컴포넌트, 스타일 디자이너/ListView 아이템 디자이너, 그외 매우 많은 기능 개선
  • 멀티-디바이스 디자이너 개선 - 장치의 폼디자이너 미리보기, 안드로이드 웨어와 새로운 FireUI 뷰
  • Iot 또는 사물인터넷 - 블루투스LE 지원확장, IoT 연결 프레임워크, Z-Wave 장치 지원, ThingPoint(IoT 장치 엑세스 포인트)
  • 윈도우/VCL - 윈도우 10용 블루투스 LE 지원 포함된  WinRT 브릿지 개선, DirectX 12 지원
  • 기타 등등

두 번째 트랙, 코드 명 "Godzilla"는 가을 릴리즈로, 델파이와 C++빌더 에플리케이션을 리눅스 서버에서 실행 가능할 것입니다. 델파이용 리눅스용 서버 기술은 여름에 미리보기를 제공하고 피드 백 후 제공합니다. 리눅스 서버의 개발 목표는 다음과 같습니다.

  • WebBroker 아파치 모듈과 데이터스냅, EMS 지원
  • FireDAC 리눅스 데이터베이스 접근
  • IoT 용 콘솔 앱을 위한 리눅스 플랫폼 지원
  • 공식적으로 우분투(Ubuntu) 서버, 레드햇 엔터프라이즈 지원(수용에 따라 공식지원 대상 확장)
  • 윈도우 기반 IDE에서 크로스 컴파일, PAServer로 배포 및 디버깅
  • 인텔 64-bit 서버용 리눅스 컴파일러, LLVM 기반, ARC 지원

리눅스 서버 외의 추가 기능은 다음과 같습니다.

  • IDE의 UI 개선 및 스타일링
  • 새버전 Clang C++ 컴파일러 업데이트
  • GetIt 패키지 매니저와 인스톨러 추가 개선
  • 새로운 윈도우 10 VCL 컨트롤
  • FireMonkey 플랫폼 네이티브 컨트롤 지원 추가
  • 윈도우10 센테니얼(Centennial) 지원
  • 새로운 IOS, 안드로이드 버전 지원

자세한 내용은 아래 링크에서 원글을 참고하길 바랍니다. 로드맵의 개발 계획과 우선순위는 변경 될 수 있습니다.

 - http://community.embarcadero.com/article/news/16211-embarcadero-rad-studio-2016-product-approach-and-roadmap-2


만약, RAD Studio 10 시애틀을 사용하지 않는다면, RAD Studio 10 시애틀 구입 시 업데이트 서브스크립션에 가입하면 위 업데이트를 자동으로 받아 볼 수 있습니다.

 - 1년 유지 보수 혜택(Update Subscription) : http://www.devgear.co.kr/products/rad-studio/update-subscription/




험프리.김현수 RAD Studio 정보 RAD Studio 로드맵

[FireDAC MergeDataSet] 여러 데이터셋을 병합해 하나의 데이터셋을 구성할 수 있습니다.

2016.02.05 13:13

FireDAC의 TFDDataSet.MergeDataSet 메소드를 이용해 구조가 같은(또는 확장된) 데이터셋을 병합해 하나의 데이터셋을 구성할 수 있습니다.


제가 테스트한 목적은, 

데이터스냅으로 데이터량이 많은 데이터 중 일부분 데이터만 가져오고, 필요한 경우 추가로 가져와 병합(페이징 기능 구현) 할 목적으로 테스트 진행해 봤습니다.

TFDDataSet.MergeDataSet

지정된 데이터 셋(ASource)의 데이터와 메타데이터를 현재 데이터셋과 병합합니다.

procedure MergeDataSet(ASource: TFDDataSet; AData: TFDMergeDataMode = dmDataMerge; AMeta: TFDMergeMetaMode = mmNone);


TFDMergeDataMode

데이터셋 데이터를 병합하는 방법 지정

모드설명

데이터셋 변경 사항 커밋

dmNone

데이터를 병합하지 않습니다.

-

dmDataSet

원 데이터셋 클리어 후 지정된 데이터셋의 레코드를 대신 삽입합니다.

dmDataAppend

지정된 데이터셋의 레코드를 원 데이터셋에 덧붙입니다.

dmDataMerge

지정된 데이터셋의 레코드의 기본 키를 취득하고 그것과 같은 기본 키 대응 레코드를 원 데이터셋에서 찾습니다. 그 후 다음 중 하나를 수행합니다.

  • 이 데이터셋의 레코드에 해당하는 레코드가 지정된 데이터셋에있는 경우, 해당 레코드에서이 데이터셋의 레코드를 업데이트합니다.
  • 지정된 데이터셋의 레코드에 해당하는 레코드가이 데이터셋에 없는 경우는 지정된 데이터셋의 레코드가 새 레코드로이 데이터셋에 추가됩니다.
  • 해당 레코드가 삭제 된 레코드가 있으면 그것을 삭제합니다.

dmDeltaSet

원 데이터셋을 지우고 지정된 데이터셋의 레코드를 대신 삽입합니다.

아니오

dmDeltaAppend

지정된 데이터셋의 레코드를 원 데이터셋에 덧붙입니다.

아니오

dmDeltaMerge

지정된 데이터셋의 레코드의 기본 키를 취득하고 그것과 같은 기본 키 대응 레코드를 원 데이터셋에서 찾습니다. 그 후 다음 중 하나를 수행합니다.

  • 이 데이터셋의 레코드에 해당하는 레코드가 지정된 데이터셋에있는 경우, 해당 레코드에서이 데이터셋의 레코드를 업데이트합니다.
  • 지정된 데이터셋의 레코드에 해당하는 레코드가이 데이터셋에 없는 경우는 지정된 데이터셋의 레코드가 새 레코드로이 데이터셋에 추가됩니다.
  • 해당 레코드가 삭제 된 레코드가 있으면 그것을 삭제합니다.

아니오

TFDMergeMetaMode

데이터셋 메타데이터 병합하는 방법 지정

모드설명
mmNone메타 데이터의 비교 및​​ 병합을하지 않습니다.
mmMerge

지정된 데이터 집합에서 열 이름을 검색하여 이름이 같은 열이 데이터셋에서 찾습니다. 그 후 다음 중 하나를 수행합니다.

  • 지정된 데이터셋의 메타 데이터에서이 데이터셋의 열의 데이터 형식과 크기를 업데이트합니다 (같은 이름의 열만).
  • 같은 이름의 열이 데이터셋에서 찾을 수없는 경우 새 열을 데이터셋에 추가합니다.
mmAdd

지정된 데이터 집합에서 열 이름을 검색하여 이름이 같은 열이 데이터셋에서 찾습니다. 같은 이름의 열이 데이터셋에서 찾을 수없는 경우 새 열을 데이터셋에 추가합니다.

mmUpdate

지정된 데이터 집합에서 열 이름을 검색하여 이름이 같은 열이 데이터셋에서 찾습니다. 같은 이름의 열이 데이터셋에서 발견 된 경우 해당 열의 데이터 형식과 크기를 지정된 데이터셋의 메타 데이터로 업데이트합니다.

mmAddOrError

이 데이터셋의 메타 데이터를 다음과 같이 업데이트합니다.

  • 이 데이터셋에 열이없는 경우는 mmAdd 모드를 적용합니다.
  • 그렇지 않으면 mmError 모드를 적용합니다.
mmError

지정된 데이터 집합에서 열 이름을 검색하여 이름이 같은 열이 데이터셋에서 찾습니다. 동명의 열이 없거나, 동명의 열 데이터 형식이나 크기가 일치하지 않는 경우는 예외를 전달합니다.

TFDDataSet.MergeDataSet 데모


해당 데모는 왼쪽에 표시되는 3개 데이터셋(memList, memList2, memDetail)을 병합해 오른쪽에 표시되는 데이터셋(memMerge)으로 병합합니다.

병합할 대상 데이터는 같은 구조(ID, Name)의 데이터셋 2개와 확장된 구조(ID, Name, addr)를 데이터셋을 병합합니다.


작성하며 주의할 점은, 

  1. 병합해 넣을 데이터셋(memMerge)에 기본키가 설정되어 있어야 합니다. => 아래 코드에서 "memMerge.Table.PrimaryKey := memDetail.Table.PrimaryKey;"
  2. 필드 종류가 다른 데이터셋(memDetail)을 병합할 경우, 병합할 데이터셋(memMerge)에 데이터가 있을 경우 메타데이터를 변경할 경우(mmMerge) 코드 내부에서 데이터셋 메타데이터(필드 정보)를 재 생성 함. 이때 기본키가 설정되지 않아 위 1번 오류 발생 -> 미리 필드를 생성 후 mmMerge 호출하지 말 것(필드 종류가 다를 경우에 한함)

procedure TForm1.Button1Click(Sender: TObject);
begin
  // 필드 추가
  memList.FieldDefs.Add('ID', ftInteger, 0, False);
  memList.FieldDefs.Add('Name', ftString, 20, False);
  memList.CreateDataSet;

  memList2.FieldDefs.Add('ID', ftInteger, 0, False);
  memList2.FieldDefs.Add('Name', ftString, 20, False);
  memList2.CreateDataSet;

  memDetail.FieldDefs.Add('ID', ftInteger, 0, False);
  memDetail.FieldDefs.Add('Name', ftString, 20, False);
  memDetail.FieldDefs.Add('addr', ftString, 50, False);
  memDetail.CreateDataSet;

  // 데이터 추가
  memList.Open;
  memList.AppendRecord([1, '김현수']);
  memList.AppendRecord([2, '홍길동']);
  memList.AppendRecord([3, '유관순']);

  memList2.Open;
  memList2.AppendRecord([4, '김원경']);
  memList2.AppendRecord([5, '박범용']);

  memDetail.Open;
  memDetail.AppendRecord([1, '김현수', '인천']);

  // Field 복사: 미리 복사하지 않으면 Detail 머지 시 PK 설정되지 않음
  memMerge.MergeDataSet(memDetail, dmNone, mmMerge);
  // 병합해 넣을 데이터셋(memMerge)에 기본키가 설정되어 있어야 함. 기본키가 없으면 'no destination key defined' 오류 발생
  memMerge.Table.PrimaryKey := memDetail.Table.PrimaryKey;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  memMerge.MergeDataSet(memList, dmDataMerge, mmNone);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  memMerge.MergeDataSet(memList2, dmDataMerge, mmNone);
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  memMerge.MergeDataSet(memDetail, dmDataMerge, mmNone);
end;

참고



험프리.김현수 데이터 엑세스 FireDAC

델파이 iOS Touch ID 구현하기(래퍼 클래스)

2016.01.28 13:33


Touch ID는 애플 iOS의 LocalAuthentication 프레임워크 통해 구현할 수 있습니다.애플의 Touch ID는 애플의 지문인식 시스템입니다.


델파이에서 Touch ID를 구현하기 위해 LocalAuthentication 프레임워크를 델파이로 래핑한 iOSapi.LocalAuthentication.pas를 다운로드 받아 시스템 PATH에 등록된 경로에 복사합니다.


iOSapi.LocalAuthentication.pas 소스파일 다운로드 및 사용법과 설명은 아래 링크에서 가능합니다.(영문)





험프리.김현수 파이어몽키 ios

  1. Blog Icon
    섭이~

    안드로이드쪽 지문인식은 현제 불가능한가요?

[교육] 미니프로젝트과정 - 자료

2016.01.14 14:23
과정소개


요구사항 분석





다음 기능은 데이터 모듈에 함수를 정의해 구현할 것
  • 프로젝트 수행인원 추가 / 삭제
  • 프로젝트 삭제
    function AppendProjectMember(const APrjSeq, AMemSeq: Integer): Boolean;
    function DeleteProjectMember(const APrjSeq, AMemSeq: Integer): Boolean;

    function DeleteProject(const APrjSeq: Integer): Boolean;

데이터셋 상태

인터베이스 데이터베이스와 스크립트

PRJMNG.GDB


PrjMngScript.sql


데이터모듈에서 데이터 연결을 재설정 하세요.

DataAccessModule > conPrjMng(더블클릭: FireDAC Connection Editor) > Database 재설정


참고소스

데이터셋 제어


DataSetTest.zip



Form 생성과 해제


FormCreate.zip


현대식 문법


ModernLanguageFeatures.zip


프로젝트 관리 데모


ProjectManagerDemo.zip


참고링크


DynamicCreateSeat.zip


var

  I, Idx: Integer;

  Item: TListItem;

  Group: TListGroup;

  GroupText, ItemText: string;

begin

  GroupText := Edit1.Text;

  ItemText := Edit2.Text;


  Group := nil;

  for I := 0 to ListView1.Groups.Count - 1 do

  begin

    if LIstView1.Groups.Items[I].Header = GroupText then

    begin

      Group := LIstView1.Groups.Items[I];

      Break;

    end;

  end;

  if Group = nil then

    Group := ListView1.Groups.Add;


  Group.Header := GroupText;

  Item := ListView1.Items.Add;

  Item.Caption := ItemText;

  Item.GroupID := Group.ID;




험프리.김현수 교육, 세미나

[팁] 온라인상에서 바이러스를 진단 하세요. - 구글 Virus Total

2016.01.06 14:15

온라인 상에서 파일의 바이러스 감염여부를 체크해 주는 서비스입니다. 구글에서 서비스하고 있습니다.

 - https://www.virustotal.com/ko/ 


배포 전 실행파일 등을 위 사이트에서 검사하면 더욱 안전하겠네요.



54 종의 안티 바이러스를 대상으로 체크할 수 있습니다.(2016년 1월 6일 현재)


제공하는 안티바이러스 종류

ALYac

AVG

AVware

Ad-Aware

AegisLab

Agnitum

AhnLab-V3

Alibaba

Antiy-AVL

Arcabit

Avast

Avira

Baidu-International

BitDefender

Bkav

ByteHero

CAT-QuickHeal

CMC

ClamAV

Comodo

Cyren

DrWeb

ESET-NOD32

Emsisoft

F-Prot

F-Secure

Fortinet

GData

Ikarus

Jiangmin

K7AntiVirus

K7GW

Kaspersky

Malwarebytes

McAfee

McAfee-GW-Edition

MicroWorld-eScan

Microsoft

NANO-Antivirus

Panda

Qihoo-360

Rising

SUPERAntiSpyware

Sophos

Symantec

TheHacker

TrendMicro

TrendMicro-HouseCall

VBA32

VIPRE

ViRobot

Zillya

Zoner

nProtect


비슷한 서비스를 제공하는 사이트들

  • http://virscan.org/


험프리.김현수 기타정보

[마이그레이션][팁] 유니코드 검토 대상 분석 도구

2015.11.16 18:08

유니코드 검토 대상 분석 도구

유니코드 적용 시 검토해야 할 부분(함수, 자료형)을 안내해 주는 도구입니다.

Change 버튼을 눌러 경러 선택 후 Process files 버튼을 누르면 해당 경로의 유닛파일(*.pas)을 분석 후 결과를 표시합니다.


다운로드

제가 기능을 추가한 실행파일은 아래에서


Unicode_statistics_tool_Parser.zip

  • 검토 대상 총 갯수 메모 마지막에 표시 하도록 수정
  • 디렉토리 경로 문자열을 에디터에 복사해도 적용되록 수정
  • 하단 트리뷰와 레포트 파일에 검토대상이 없는 소스코드 표시되지 않도록 수정


원본 실행파일과 소스코드

http://cc.embarcadero.com/item/27398

분석 대상

다음 함수와 자료형을 대상으로 분석하며, 하단 Add Token 기능으로 대상을 추가할 수 있습니다.


SizeOf

Length

FillChar

Move

Char

PChar

AnsiChar

PAnsiChar

String

ShortString

Chr

Ord

SaveToFile

LoadFromFile

Read

ReadBuffer

Write

WriteBuffer

MultiByteToWideChar

AppendStr

GetProcAddress

CreateProcess

Copy

Seek

Pointer

AllocMem

GetMem

StrAlloc

AnsiStrAlloc



험프리.김현수 마이그레이션

[마이그레이션] 유니코드 적용시 검토할 사항들

2015.11.09 18:58

델파이 2009 이후 버전 부터는 유니코드 기반의 문자열을 사용합니다. 그래서 델파이 2007 이전버전에서 델파이 2009 이후 버전으로 마이그레이션 할 경우 소스코드에서 유니코드 사용에 대한 점검이 필요합니다.


일부 개발자들이 유니코드 대응을 마이그레이션의 큰 위험요소로 생각합니다. 하지만 알고 보면 대부분의 경우 기존 소스코드를 별도 추가작업 없이 유니코드 기반에서 그대로 사용할 수 있습니다. 단, 문자열을 다루는 코드에 대해서는 점검이 필요합니다.


유니코드와 델파이의 변경사항에 대해 살펴보고 기존코드를 유니코드 기반 델파이에서 동작하도록 점검하는 내용을 살펴보겠습니다.

목차

1. 유니코드와 델파이의 변경사항

  1.1. 유니코드란?

  1.2. 유니코드 지원에 의한 델파이 변경사항

2. 기존 코드를 유니코드 기반 델파이에서 동작하도록 수정하기

  2.1.. 유니코드 적용 시 검토 대상

  2.2. 유니코드 검토 대상 분석 도구 안내


1, 유니코드와 델파이의 변경사항

1.1. 유니코드란?

유니코드는 사실상 모든 문자들을 단일 캐릭터 셋으로 인코딩할 수 있는 문자 인코딩 방식입니다. 델파이는 2009 버전부터 IDE와 컴파일러, RTL, VCL 모두 완벽하게 유니코드를 지원합니다.

유니코드에 대한 자세한 내용은 닉하지스가 작성한 글을 박지훈님이 번역한 글과 엠바카데로 기술문서를 통해 더 자세히 확인할 수 있습니다.


1.2. 유니코드 지원에 의한 델파이 변경사항

델파이에서 유니코드 지원 시 변경된 사항은 다음과 같습니다.

  1. 문자열의 데이터 타입 선언의 변경

  2. 문자열 길이의 변경

  3. 문자 크기의 변경


문자열 데이터 타입 선언의 변경

 데이터 타입

 유니코드 지원하지 않는 버전

 (델파이 2007 이전)

 유니코드 지원하는 버전

 (델파이 2009 이후)

 string

 AnsiString

 UnicodeString

 Char

 AnsiChar

 WideChar

 PChar

 PAnsiChar

 PWideChar

 PAnsiChar

 PAnsiChar

 PAnsiChar

 PWideString

 PWideChar

 PWideChar

 AnsiString

 AnsiString

 AnsiString

 WideString

 WideString

 WideString


위 표와 같이 string은 유니코드 지원하지 않는 버전에서는 AnsiString으로, 유니코드를 지원하는 버전에서는 UnicodeString으로 선언됩니다. Char와 PChar도 선언된 데이터 타입에 차이가 있습니다.

반면, 명시적으로 Ansi, Wide가 포함된 데이터 타입은 유니코드 지원여부와 관계없이 동일한 데이터타입으로 사용됩니다.


문자열 길이의 변경

델파이는 유니코드 지원과 하위 호환성을 확보하기 위해 대부분의 문자열 함수가 UnicodeString과 AnsiString 두가지 데이터를 처리할 수 있도록 구현되었습니다.

즉, Length(문자열) 함수는 UnicodeString을 타입 문자열을 처리하는 Length함수와 AnsiString 타입 문자열을 처리하는 Length함수를 모두 제공합니다.

하지만, 같은 함수를 이용하더라도 캐릭터셋 특성 상 Length 함수는 UnicodeString과 AnsiString의 길이를 다르게 반환합니다.


 

 string(UnicodeString)

 AnsiString

 Length('한글1'); 

 3

 5

문자열 길이 변경에 따른 유의사항은 다음 장에서 다루도록 하겠습니다.


문자 크기의 변경

UnicodeString의 모든 문자의 크기는 2Bytes입니다. 이제 한글 한글자도 2Bytes, 영문 한자도 2Bytes, 숫자 한자도 2Bytes 모두 2Bytes입니다.

.

2. 기존 코드를 유니코드 기반 델파이에서 동작하도록 수정하기

델파이에서 유니코드를 지원은 재검토 대상의 경우를 제외하고는 별도의 추가작업 없이 기존 코드를 그대로 사용할 수 있습니다.

2.1. 유니코드 적용 시 검토 대상

  • string 길이와 데이터 크기가 같다고 간주한 코드
  • char 데이터 크기를 1로 간주한 코드
  • string을 AnsiString으로 간주한 코드
  • 잠재적으로 수정될 필요가 있을 수 있는 코드

string 길이와 데이터 크기가 같다고 간주한 코드

UnicodeString 기반에서는 더이상 문자열(string)의 길이와 데이터 크기가 같지 않습니다.

UnicodeString의 Length 함수는 문자의 수를 반환하고, 문자의 크기는 2Bytes이기 때문에 문자열의 데이터 크기는 "문자열 길이 * SizeOf(Char)"로 계산하도록 코드를 전환해야 합니다.


다음 예제를 통해 확인합니다.

var
  Count: Integer;
  Buf1, Buf2: array[0..13] of Char;
begin
  Buf1 := '가나다라마바사아자차카타파하';
  // 잘못됨: AnsiString과 같이 길이로 데이터 복사
  Move(Buf1, Buf2, Length(Buf1)); // Buf2 = 가나다라마바사
  // 올바른: 문자열 길이와 문자 크기의 곱으로 데이터 복사
  Move(Buf1, Buf2, Length(Buf1) * SizeOf(Char)); // Buf2 =가나다라마바사아자차카타파하
end;

이제 기존과 같이 문자열을 길이로 복사하면 절반의 데이터만 복사된다는 점 유의하기바랍니다.


검토해야하는 대표적인 키워드(함수, 데이터타입)는 아래와 같습니다. 

 Length

 FillChar

 Read

 ReadBuffer

 Write

 WriteBuffer

 Copy

 Seek

 AllocMem

 GetMem

 StrAlloc

 AnsiStrAlloc

 Delete Insert Pos LeftStr RightStr MidStr
 Move     

기타, 메모리를 할당하고 복사하는 코드와 문자열 길이를 이용해 문자열을 조작하는 코드를 점검하시기 바랍니다.


Char 데이터 크기를 1로 간주한 코드

UnicodeString에서 Char의 데이터 크기는 2Bytes 입니다. 기존 코드에서 Char가 1Bytes로 가정하고 구현한 코드를 점검해야 합니다.


다음 예제는 문자열을 버퍼로 사용한 코드입니다. 문자열은 조작이 쉽기 때문에 예제와 같이 Char 배열 선언후 메모리에 복사하는 코드를 사용했다면, 데이터 크기가 기존에 비해 2배로 커질것 입니다. 

var Buf: array[0..3] of Char;
begin
  Buf1 := 'abcd';

  MemStream := TMemoryStream.Create;
  try
    MemStream.Write(Buf1, SizeOf(Buf1)); // SizeOf(Buf): Ansi=4, Wide=8
  finally
    MemStream.Free;
  end;
end;

이 경우, 문자를 1Byte로 사용해야 하는 경우 array of AnsiChar로 수정해야 하고, 데이터를 읽고, 쓰는 부분을 쌍으로 데이터가 일치하도록 점검하기 바랍니다.


그리고 문자열 Set 문법은 Char가 WideChar로 선언되어 있기 때문에 아래 예제와 같이 CharInSet 함수를 사용해야 합니다.

var C: Char;
begin
  C := Edit1.Text[1];

  // if C in ['a'..'z', 'A'..'Z'] then
  if CharInSet(C, ['a'..'z', 'A'..'Z']) then
  begin
    Label1.Caption := 'It is there';
end;


검토해야하는 대표적인 키워드(함수, 데이터타입)는 아래와 같습니다. 

 SizeOf

 Char

 of Char

 in

 

 



string을 AnsiString으로 간주한 코드

델파이 2007 이전 버전에서는 string이 곧 AnsiString, PChar가 PAnsiChar였기 때문에 별다른 생각없이 string과 PChar 데이터 타입을 사용한 코드가 있을 수 있습니다.


특히, DLL과 문자열 전달 시 문자열포인터로 PChar를 전달한 경우 아래와 같이 조치해야 합니다.

  • DLL을 직접 제작한 경우 유니코드 지원이 필요하다면 DLL과 DLL을 호출하는 실행파일 모두 Export 메소드의 문자열 포인터 데이터 타입을 PWideChar로 변경 후 다시 빌드해 사용해야 합니다.

  • DLL을 직접 제작하지 않은 경우 DLL 인터페이스 문서를 참고해 유니코드를 지원하는 메소드 여부 확인 후, PAnsiChar, PWideChar를 명시적으로 지정해야 합니다.

델파이에서도 내부적으로 윈도우 API를 호출합니다. 델파이도 위와 마찮가지로 AnsiString인 경우 PAnsiChar 메소드를 UnicodeString인 경우 PWideChar 메소드(보통 같은 메소드이름 마지막에 W가 붙은경우 WideChar 메소드입니다.)를 호출합니다.

만약, 윈도우 API를 직접 호출한 경우 아래와 같이 조치하기 바랍니다.

  • 유니코드를 지원하는 메소드(메소드명이 W로 끝나는 메소드)를 찾아 변경합니다.

  • 메소드가 유니코드를 지원하지 않는 경우 전달하는 문자열을 PAnsiChar로 형변환해 전달해야 합니다.

PAnsiChar로 형변환 시 데이터 손실이 발생할 수 있어 먼저 AnsiString으로 변환 후 PAnsiChar로 변환해야 합니다.(string을 바로 PAnsiChar로 변환 시 string에 영문이 있는 경우 무조건 그 다음 바이트에 0이 들어가 널바이트 문자열 처리하는 문자열 포인터에 일부 문자열만 전달됩니다.)
다음 예제와 같이 PAnsiChar로 형변환 후 데이터를 전달해야 합니다.
var path: string;
begin
  path := 'C:\Program Files\Internet Explorer\iexplore.exe';
  WinExec(PAnsiChar(AnsiString(path)), SW_SHOW);
end;

검토해야하는 대표적인 키워드(함수, 데이터타입)는 아래와 같습니다. 

 PChar

 AnsiChar

 PAnsiChar

 Pointer

 AppendStr

 GetProcAddress

 CreateProcess

 Chr

    



잠재적으로 수정될 필요가 있을 수 있는 코드

  • “of Char” 텍스트와 “of AnsiChar” 텍스트를 검색하여 버퍼가 유니코드에 맞게 사용되었는지 확인합니다. 

  • “string[” 텍스트를 검색하여 스트링 인덱스의 문자가 대입되는 변수가 Char(즉 WideChar)가 아닌 AnsiChar 타입 변수로 지정되도록 수정합니다. 

  • “AnsiString”, “AnsiChar”, “PAnsiChar”를 명시적으로 지정한 부분을 찾아 그럴 필요가 있고 제대로 되어 있는지 확인합니다. 

  • “ShortString”을 명시적으로 지정한 부분을 찾아 그럴 필요가 있고 제대로 되어 있는지 확인합니다. 

  • “Length(” 텍스트를 검색하여 Length가 SizeOf와 동일한 의미로 사용되지는 않았는지 확인합니다. 

  • “Copy(” , “Seek(” , “Pointer(” , “AllocMem(”, “GetMem(” 텍스트를 검색하여 스트링 혹은 문자 배열에 대해 제대로 동작하는지 확인합니다.


다음 내용을 통해 유니코드 적용에 대한 내용을 더 살펴볼 수 있습니다.

2.3. 유니코드 검토 대상 분석 도구 안내

위에서 소개한 유니코드 적용 시 검토 대상을 분석하고, 안내해 주는 도구입니다. 아래 링크에서 다운로드 할 수 있습니다.


마이그레이션 참고 리소스




험프리.김현수 마이그레이션

[데이터스냅] 데이터스냅 클라이언트에서 TCP/IP로 접속 시 ConnectTimeout이 적용되지 않는 경우 대처방법

2015.11.04 15:55

(이글은 RAD 스튜디오 10 시애틀 기준으로 테스트하고, 작성되었습니다. 다른 버전 사용자들은 이슈 발생여부를 먼저 확인하고 아래 내용을 참고하시기 바랍니다.)


이 글은 데이터스냅 클라이언트에서 TCP/IP로 접속 시 Timeout이 적용되지 않는 이슈에 대해 원인을 확인하고 회피하는 내용을 소개합니다.


데이터스냅 클라이언트 프로그램에서 서버에 접속하기 위해 SQLConnection을 사용합니다.


연결방식(CommunicationProtocol)은 tcp/ip, http, https가 있습니다.

Timeout 속성은 CommnunicationTimeout(송수신 시간제한)과 ConnectTimeout(연결 시간제한) 두가지가 있습니다.


결론적으로 Timeout 속성이 적용되지 않는 경우는 tcp/ip 연결방식으로 연결한 경우 두가지 Timeout 속성이 모두 적용되지 않습니다.(http, https 연결방식에서는 Timeout이 정상 적용됩니다.)

이미 엠바카데로 QC에 이슈가 등록되었지만 적용되지 않는다는 답변으로 아쉽게 마무리되었습니다.

http://qc.embarcadero.com/wc/qcmain.aspx?d=80954#sthash.9Apdxn5i.dpuf


제일  손쉬운 조치방법은 CommunicationProtocol을 http로 변경하는 것입니다.(물론 데이터스냅 서버에서 http를 지원해야 합니다.)


만약, TCP/IP로 연결하실 분들은 아래 내용을 참고하세요.
(RAD 스튜디오 10 시애틀에서 진행했습니다. 다른 버전 사용자분들은 참고해서 수정하시기 바랍니다.)

총 2개의 Unit을 수정하면됩니다. 
아래 2개 파일을 프로젝트 파일 경로로 복사 후 프로젝트에 추가(Add) 합니다.(즉, 해당 프로젝트에서만 수정된 내용이 반영됩니다.)
  • Data.DbxSocketChannelNative.pas(C:\Program Files (x86)\Embarcadero\Studio\17.0\source\data\dbx)
  • IPPeerClient.pas(C:\Program Files (x86)\Embarcadero\Studio\17.0\source\indy\implementation)

Data.DbxSocketChannelNative.pas(C:\Program Files (x86)\Embarcadero\Studio\17.0\source\data\dbx)
procedure TDBXIdTCPLayer.Open(const DBXProperties: TDBXProperties);
var
  timeout: string;
  commTimeout: string;
  LIPVersionStr: string;
  LIPVersion: Integer;
begin
  Close;
  FIPImplementationID := DbxProperties[TDBXPropertyNames.IPImplementationID];
  if FIdSocket = nil then
    FIdSocket := CreateClientSocket;
  FIdSocket.Host := DbxProperties[TDBXPropertyNames.HostName];
  FIdSocket.Port := DbxProperties.GetInteger(TDBXPropertyNames.Port);

  LIPVersionStr := DbxProperties[TDBXPropertyNames.CommunicationIPVersion].Trim;
  LIPVersion := GetEnumValue(TypeInfo(TIPVersionPeer), LIPVersionStr);
  if LIPVersion > -1 then
    FIdSocket.IPVersion := TIPVersionPeer(LIPVersion)
  else
    FIdSocket.IPVersion := TIPVersionPeer.IP_IPv4;

  timeout := DbxProperties[TDBXPropertyNames.ConnectTimeout];
  if timeout = '' then
    ConnectTimeout := 0
  else
    ConnectTimeout := StrToInt(timeout);
  commTimeout := DbxProperties[TDBXPropertyNames.CommunicationTimeout];
  if commTimeout = '' then
    CommunicationTimeout := 0
  else
    CommunicationTimeout := StrToInt(commTimeout);

  { Added Humphrey}
  // ConnectTimeout과 CommunicationTimeout을 FIdSocket에 전달
  if Supports(FIdSocket, IIPPeerClientSetTimeout) then
  begin
    (FIdSocket as IIPPeerClientSetTimeout).SetConnectTimeout(ConnectTimeout);
    (FIdSocket as IIPPeerClientSetTimeout).SetReadTimeout(CommunicationTimeout);
  end;
{ Added Humphrey}

  FIdSocket.UseNagle := false;
  FIdSocket.Connect;

  FConnected := false;
end;
위 메소드는 tcp/ip로 데이터스냅 클라이언트가 접속하는 일부 소스코드입니다.
주의깊게 볼 부분은 ConnectTimeout과 CommunicationTimeout 값을 가져오고 FIdSocket에 전달하는 내용이 누락되었습니다.
그래서 "Added Humphery" 주석으로 감싸진 내용을 추가했습니다.
uses 절에 IPPeerClient 추가해야 합니다.

IPPeerClient.pas(C:\Program Files (x86)\Embarcadero\Studio\17.0\source\indy\implementation)
interface
  { Added Humphrey}
type
  IIPPeerClientSetTimeout = interface
    ['{9924134C-9C7D-464F-8ABE-F3E1E408C566}']
    procedure SetConnectTimeout(const ATimeout: Integer);
    procedure SetReadTimeout(const ATimeout: Integer);
  end;
{ Added Humphrey}
상단 interface 아래에 IIPPeerClientSettimeout 인터페이스 추가

  TIdTCPClientPeerIP = class(TIdClassIP, IIPTCPClient, IIPObject{ Added Humphrey}, IIPPeerClientSetTimeout{ Added Humphrey})
  private
    FTCPClient: TIdTCPClientIP;
    FIOHandler: IIPIOHandler;
    FSocket: IIPIOHandlerSocket;
  protected
    function Connected: Boolean;
    function GetSocket: IIPIOHandlerSocket;
    procedure SetIOHandler(Handler: IIPIOHandler);
    function GetIOHandler: IIPIOHandler;
    function GetBoundIP: string;
    procedure SetBoundIP(IP: string);
    function GetHost: string;
    procedure SetHost(LHost: string);
    function GetPort: TIPPortPeer;
    procedure SetPort(LPort: TIPPortPeer);
    procedure SetIPVersion(const AValue: TIPVersionPeer);
    function GetIPVersion: TIPVersionPeer;
    function GetUseNagle: Boolean;
    procedure SetUseNagle(Use: Boolean);
    procedure Connect;
    procedure Disconnect;
    function GetManagedIOHandler: Boolean;
    procedure SetManagedIOHandler(AManagedIOHandler: Boolean);
  public
    function GetObject: TObject;
    function GetIPImplementationID: string;
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
{ Added Humphrey}
    procedure SetConnectTimeout(const ATimeout: Integer);
    procedure SetReadTimeout(const ATimeout: Integer);
{ Added Humphrey}
  end;
TIdTCPClientPeerIP 클래스 선언부에 위 IIPPeerClientSetTimeout 인터페이스 위임, 인터페이스 메소드 추가

구현부에 타임아웃 적용하도록 구현
{ Added Humphrey}
procedure TIdTCPClientPeerIP.SetConnectTimeout(const ATimeout: Integer);
begin
  FTCPClient.ConnectTimeout := ATimeout;
end;

procedure TIdTCPClientPeerIP.SetReadTimeout(const ATimeout: Integer);
begin
  FTCPClient.ReadTimeout := ATimeout;
end;
{ Added Humphrey}
위와 같이 조치하면 TSQLConnection으로 DataSnap을 TCP/IP로 연결하는 경우에도 Timeout 속성이 모두 적용됩니다.

완성된 소스코드는 저작권 문제(?)로 올려놓지 못하니 양해부탁드리며 필요하신 분들은 개인적으로 요청 해주세요.


험프리.김현수 파이어몽키

  1. Blog Icon

    비밀댓글입니다

[따라하기] 건강데이터 수집 및 기록 시스템 #1 - BLE 기반 스마트 체중계에서 실시간 데이터 받기

2015.10.02 13:06


위 동영상(건강데이터 수집 및 기록 시스템 데모) 중 스마트 체중계의 체중정보를 모바일에서 실시간으로 받아오는 기능을 따라하기로 진행합니다.


스마트 체중계에서 체중정보 수신앱 만들기

❑ 앱소개

앱소개

이 앱은 스마트체중계와 블루투스 LE로 연결 해 체중정보를  실시간으로 받아와 화면에 표시하는 앱입니다.

따라하기의 목적

스마트 체중계 연결을 통해 블루투스 LE 인터페이스를 제공하는 다양한 기기(또는 센서)에 연결하고 데이터를 수신하는 방법을 이해합니다.


따라하기에서는 다음 내용을 다룹니다.

  • RAD Studio로 멀티-디바이스(안드로이드, iOS, 윈도우, OS X) 앱 프로젝트 생성 및 화면 디자인
  • TBluetoothLE 컴포넌트로 스마트 체중계와 연결 및 데이터 수신(구독)
  • 실 기기에 배포 및 테스트(안드로이드 폰, 아이폰)

따라하기

0, 사전 준비사항

1, 빈 멀티-디바이스 애플리케이션 프로젝트 생성

2, 메인 UI 제작

3, 블루투스LE 컴포넌트 추가

4, 주변의 디바이스 탐색

5, 탐색된 디바이스 목록에서 디바이스 선택 후 서비스 탐색

6, 탐색된 서비스 목록에서 서비스를 선택 후 특성 구독

7, 특성 데이터 수신 후 체중 데이터 가져오기

8, 블루투스 권한설정 

9, 디바이스에 배포 및 테스트

0, 사전 준비사항

개발도구 준비하기

델파이(또는 RAD Studio)를 이용해 실습 진행합니다.(이 실습은 델파이 10 시애틀 버전으로 작성되었습니다. 델파이 XE8 이상에서 따라할 수 있습니다.) 

만약, 델파이가 설치되지 않았다면 아래의 페이지에서 델파이를 다운로드 받아 설치 후 진행하시기 바랍니다. 

스마트 체중계 준비하기

따라하기에서는 Wahoo Balance Bluetooth Smart Scale 제품을 이용해 실습을 진행합니다.

https://www.underarmour.com/en-us/wahoo-balance-bluetooth-smart-scale/pid1276806-100-OSFA


Wahoo Balance Bluetooth Smart Scale은 다음과 같은 디바이스 이름과 UUID를 갖습니다.

디바이스 이름 : Wahoo Scale v1.3

서비스 UUID : 00001901-0000-1000-8000-00805F9B34FB

특성 UUID : 00002B01-0000-1000-8000-00805F9B34FB

위 정보는 구현에 필요한 정보입니다.(시중의 다른 스마트 체중계는 위 값들이 다릅니다.)

BLE 구조에 대한 소개

블루투스 LE는 프로파일(Profile), 서비스(Service), 특성(Characteristic) 기반으로 아래 그림과 같이 프로파일은 하나 이상의 서비스를 갖고, 서비스는 하나이상의 특성을 갖는 계층구조로 구성되어 있습니다.



(출처: GENERIC ATTRIBUTE PROFILE (GATT) - https://developer.bluetooth.org/TechnologyOverview/Pages/GATT.aspx)


블루투스 LE 인터페이스를 제공하는 장비와 연결하고 데이터를 받기 위해 다음 과정이 필요합니다.(실제 구현도 다음 단계대로 진행합니다.)

1, 주변의 블루투스 LE 프로파일을 탐색합니다.

2, 탐색된 프로파일에서 서비스를 탐색합니다.

3, 탐색된 서비스에서 특성을 찾아 구독(subscribe)합니다.

4, 구독한 특성에서 발생되는 특성값에서 필요한 데이터를 추출합니다.

1, 빈 멀티-디바이스 애플리케이션 프로젝트 생성

  1. File > New > Multi-Device Application - Delphi 메뉴를 선택 하고, Blank Application을 선택해 프로젝트를 생성합니다.
  2. File > Save all 메뉴를 선택 해 유닛이름을 "MainForm.pas"로 프로젝트 이름을 "SmartScale.dproj"로 저장합니다.

2, 메인 UI를 제작

모바일 앱 스타일로 화면 구성하기 위해 폼디자이너 스타일을 Android로 변경합니다.


다음화면과 표를 이용해 체중정보 수신 앱 메인 UI를 개발합니다.


상위 오브젝트 

오브젝트 

속성 

값(또는 설명) 

 Form1

 ToolBar1

 

 

 Layout1

 Align

 Top
 Height 81
 Memo1

 Align

 Client

 ToolBar1

 Label1

 Align

 Client

 Text

 스마트 체중계 데모

 TextSettings.HorzAlign

 Center

 Switch1 Align Right
 Layout1 Text1

 Align

 Center

 Text

 0.0
 TextSettings.Font.Size

 30

 TextSettings.HorzAlign Trailing
 Width 114
 Text1 Text2 Position.X 120
 Text Kg

 TextSettings.HorzAlign

 Leading

3, 블루투스 LE 컴포넌트 추가

블루투스 LE 컴포넌트 추가

Tool Palette에서 TBluetoothLE 컴포넌트 선택 해 폼에 추가합니다.


필요한 변수, 메소드, 상수 추가

구현에 필요한 변수(디바이스, 서비스, 특성), 메소드 선언(시작, 중지), 상수(장비명과 서비스, 특성 UUID)를 아래와 같이 추가합니다.

  private
    { Private declarations }
    FBLEDevice: TBluetoothLEDevice;
    FBLEGattService: TBluetoothGattService;
    FBLEGattChar: TBluetoothGattCharacteristic;

    procedure StartScale; // 체중계 연결 동작 시작(블루투스LE 활성화, 주변 디바이스 탐색)
    procedure StopScale; // 체중계 연결 동작 중지(블루투스LE 비활성화, 특성 구독 해제)
  public
    { Public declarations }
  end;

const
  ScaleDeviceName = 'Wahoo';

  WEIGHT_SERVICE: TBluetoothUUID          = '{00001901-0000-1000-8000-00805F9B34FB}';
  WEIGHT_CHARACTERISTIC: TBluetoothUUID   = '{00002B01-0000-1000-8000-00805F9B34FB}';

메소드 구현부 생성

StartScale, StopScale 메소드 구현부를 자동 생성하기 위해 procedure StartScale;에 마우스 커서를 옮기고 키보드에서 Ctrl + Shift + C를 동시에 누릅니다.


4, 주변의 디바이스 탐색

주변 디바이스 탐색

Switch1의 OnSwitch 이벤트 핸드러 생성(Switch1 컴포넌트 선택 > Object Inspector 창에서 Event 탭 선택 > OnSwitch 우측의 콤보박스 더블클릭) 후 아래 코드를 입력합니다.

procedure TForm1.Switch1Switch(Sender: TObject);
begin
  if Switch1.IsChecked then
    StartScale
  else
    StopScale;
end;

StartScale 메소드에서 블루투스 LE를 활성화하고, 주변 디바이스를 탐색하는 코드를 다음과 같이 입력합니다.
(StopScale은 제일 마지막에 다시 구현합니다.)

procedure TForm1.StartScale;
begin
  BluetoothLE1.Enabled := True;
  BluetoothLE1.DiscoverDevices(1000); // 1초(1000 ms)동안 주변 디바이스 탐색, 완료 시 OnEndDiscoveryDevices 이벤트 발생
end;

5, 탐색된 디바이스 목록에서 디바이스 선택 후 서비스 탐색

StartScale 메소드의 DiscoverDevices 메소드 호출하면 (주변의 디바이스 탐색 후) OnEndDiscoverDevices 이벤트가 발생합니다. 

OnEndDiscoverDevices 이벤트는 파라메터로 탐색된 디바이스 목록(ADeviceList)을 제공합니다.

이 디바이스 목록에서 'Wahoo'(위에서 ScaleDeviceName 상수로 선언)로 시작하는 디바이스를 선택합니다.

디바이스를 선택했다면, 디바이스에서 제공하는 서비스 탐색을 시도합니다.

procedure TForm1.BluetoothLE1EndDiscoverDevices(const Sender: TObject;
  const ADeviceList: TBluetoothLEDeviceList);
var
  Device: TBluetoothLEDevice;
begin
  if ADeviceList.Count = 0 then
  begin
    Memo1.Lines.Add('발견된 디바이스가 없습니다.');
    Switch1.IsChecked := False; // 디바이스 미발견 시 스위치 끄기
    Exit;
  end;

  FBLEDevice := nil;
  Memo1.Lines.Add('Device List');
  for Device in ADeviceList do
  begin
    Memo1.Lines.Add(' - ' + Device.DeviceName); // 로그-디바이스 이름

    // 디바이스 이름으로 디바이스 선택
    if Device.DeviceName.StartsWith(ScaleDeviceName) then
    begin
      FBLEDevice := Device;
      Memo1.Lines.Add('디바이스를 찾았습니다.');
    end;
  end;

  if FBLEDevice = nil then
    Exit;

  // [TIP] 서비스 발견이 실패하는 경우가 종종 있음
    // 실패한 경우 한번더 발견요청
  if not FBLEDevice.DiscoverServices then
    FBLEDevice.DiscoverServices; // 서비스 탐색 완료 시 OnEndDiscoverServices 이벤트 발생
end;

6, 탐색된 서비스 목록에서 서비스를 선택 후 특성 구독

서비스 탐색(DiscoverServices)이 완료되면 OnEndDiscoverServices 이벤트가 발생합니다.

OnEndDiscoverServices 이벤트는 파라메터로 탐색된 서비스 목록(AServiceList)을 제공합니다.

이 서비스 목록에서 서비스 UUID와 같은 UUID를 갖는 서비스를 선택합니다.

선택한 서비스에서 특성 UUID로 특성을 찾습니다.

특성에서 체중정보를 포함한 특성데이터를 수신할 수 있도록 구독(SubscribeToCharacteristic) 합니다.

procedure TForm1.BluetoothLE1EndDiscoverServices(const Sender: TObject;
  const AServiceList: TBluetoothGattServiceList);
var
  Service: TBluetoothGattService;
begin
  Memo1.Lines.Add('Service List');
  for Service in AServiceList do
  begin
    Memo1.Lines.Add(' - ' + Service.UUID.ToString); // 로그-디바이스 이름
    if Service.UUID = WEIGHT_SERVICE then
    begin
      FBLEGattService := Service;
      Memo1.Lines.Add('서비스를 찾았습니다.');
    end;
  end;

  if FBLEGattService = nil then
  begin
    Memo1.Lines.Add('서비스를 찾지 못했습니다.');
    Exit;
  end;

  // [TIP][예외] 특성목록을 생성하기 위해 아래 코드 호출
    // GetCharacteristic 바로 호출 시 특성을 가져오지 못해
    // GetCharacteristics을 먼저 호출
  BluetoothLE1.GetCharacteristics(FBLEGattService);

  FBLEGattChar := BluetoothLE1.GetCharacteristic(FBLEGattService, WEIGHT_CHARACTERISTIC);
  if FBLEGattChar = nil then
  begin
    Memo1.Lines.Add('서비스 특성을 찾지 못했습니다.');
    Exit;
  end;

  if BluetoothLE1.SubscribeToCharacteristic(FBLEDevice, FBLEGattChar) then // 구독하면 OnCharacteristicRead 이벤트를 통해 특성 값을 받음
    Memo1.Lines.Add('특성에 구독했습니다.'); 
end;

7, 특성 데이터 수신 후 체중 데이터 가져오기

특성에 구독(SubscribeToCharacteristic)하면 TBluetooth 컴포넌트의 OnCharacteristicRead 이벤트로 특성 값을 받을 수 있습니다. 스마트 체중계의 경우 체중계의 체중이 변경될 때마다 특성 값을 받을 수 있습니다.

Wahoo Balance Blueeoth Smart Scale은 다음과 같은 코드로 특성값에서 체중 정보를 가져옵니다.

(특성 값을 분석하는 방법은 서비스마다 다릅니다.)

procedure TForm1.BluetoothLE1CharacteristicRead(const Sender: TObject;
  const ACharacteristic: TBluetoothGattCharacteristic;
  AGattStatus: TBluetoothGattStatus);
var
  Weight: Single;
begin
  Weight := (ACharacteristic.GetValueAsInteger shr 8) / 10;
    // 특성 값에서 앞의 3byte 이용, 마지막 숫자는 소숫점이므로 10으로 나누기

  Text1.Text := Format('%3.1f', [Weight]);
end;

마지막으로 앞에서 선언한 StopScale에 특성 구독을 해지하고, 블루투스 LE를 비활성화하는 코드를 추가합니다.

procedure TForm1.StopScale;
begin
  if Assigned(FBLEDevice) and Assigned(FBLEGattChar) then
    BluetoothLE1.UnSubscribeToCharacteristic(FBLEDevice, FBLEGattChar);
  BluetoothLE1.Enabled := False;
end;

8, 블루투스 권한설정

(이 과정은 안드로이드 플랫폼을 사용하지 않는 경우 생략할 수 있습니다.)

비콘은 블루투스 LE(Low Energy) 기반으로 통신합니다.  블루투스 사용권한을 설정합니다.

Project > Options 메뉴를 선택 후 Uses Permissions 화면으로 이동합니다.


Bluetooth와 Bluetooth admin 두개의 권한을 사용하도록 설정합니다.


9, 디바이스에 배포 및 테스트

처음 디바이스에 배포하는 경우 먼저 모바일 개발환경 설정하고 진행하기 바랍니다.


개발을 완료했습니다. 이제 준비된 개발환경으로 플랫폼 선택 후 Run > Run Without Debugging 메뉴를 이용해 실행하고 테스트 합니다.



테스트 방법:

  1. 디바이스의 블루투스 기능을 킵니다.
  2. 앱을 실행 후 스위치를 커서 주변의 블루투스 LE를 탐색해 스마트 체중계와 연결합니다.
    (메모 컨트롤에 "디바이스를 찾았습니다." > "서비스를 찾았습니다." > "특성에 구독했습니다." 메시지가 표시되면 정상 연결된 것입니다.)
  3. 체중계에 올라가면 실시간으로 앱에 체중정보가 표시되는 것을 확인합니다.

험프리.김현수 파이어몽키

  1. Blog Icon
    이승욱

    안녕하세요.
    지난 9월에 세미나를 교수님과 다녀온 후에 학과에서 간단하게 시연해보려고 계속 작업중에 있습니다. 비콘을 이용한 경보 앱은 구현을 하고 이번에는 체중계 앱을 작업하고 있는데 문제가 있어 조언을 얻고자 글을 남기게 되었습니다.
    기존에 포스팅 하신데로 모두 설정하였고 UUID도 맞게 입력이 되었는데 컴파일 하고 연결하려고 하면 디바이스가 1개 검색이 되지만 weight_service를 불러오지 못한다고 합니다.
    현재 작업하는 디바이스는 탭이고 개별로 블루투스로 연결해볼까 해서 연결하면 Wahoo Scale v1.3 에서 연결을 거절했다는 메시지가 뜨네요...
    답변해주시면 감사하겠습니다.

  2. 디바이스 발견 시 본문의 화면과 같이 Wahoo Scale v1.3으로 표시되나요?
    쳬중계를 연결할때 미리 체중계에 올라가 체중계를 키고 시도해 보세요.

    그리고, 혹시 모르니 다른 안드로이드 기기로도 테스트해보시기 바랍니다.
    (그럴리 없지만 체중계의 이상을 확인하려면 아이폰에서 Wahoo Wellness 앱을 설치해 연결을 확인해보세요. 무료입니다.)

    그래도 안되면 다음 링크에 데모 샘플코드가 있으니 해당 소스코드로 테스트해보시기 바랍니다.
    https://github.com/devgear/RADStudio_IoTDemos

    마지막으로 시간되시면 제가 사물인터넷 1일 과정 교육을 진행하고 있습니다.
    해당 교육에서 스마트 체중계 연결 실습도 진행되니 오프라인으로 확인하고 싶으시면 교육신청해주세요.^^
    http://devgear.co.kr/support/education/radstudio_iot.html

  3. Blog Icon
    김헌성

    안녕하세요~

    블루투스 저울로 스마트폰 앱을 만드는것을 공부하고 있습니다.

    혹시 체중계별로 UUID가 다르다고 하셨는데요..

    Wahoo Balance Bluetooth Smart Scale 이제품의 UUID는 어떻게 아신건가요??

    공개를 해주나요??아니면 다른방법으로 아는 방법이 있나요??

    저는 블루투스 정밀저울로 테스트를 해야해서요..ㅠ

    제가 테스트하려는 제품은 Smart Connect Bluetooth Kitchen Scale 입니다.

    답변주시면 감사하겠습니다. ㅎ

  4. Blog Icon
    박상우

    안녕하십니까. 비콘과 앱 개발을 처음 해보는 학생입니다.
    비콘에 대한 정확한 개념도 없이 막 시작하는 터라 궁금한 점이 한두가지가 아닌데, 초면에 무례함을 무릎쓰고 몇가지 질문 드려도 될까요?

    우선 첫 번째로 비콘을 이용하여 자동 출석체크 시스템을 만드려는데, 강의장이라고 인식되는 범위 내에 단말이 들어오면 단말에 앱 알람이 뜨며 해당 강의실의 출석 버튼이 오픈되고, 출석 버튼을 누르면 출석이 인정되게 하는 앱을 구현하고 싶습니다. 가능할지 궁금합니다.

    첫번째단계까지 구현하고 난 다음에는 출석 후 단말이 30분 이상 해당 지역에 없으면 출석인정이 안되도록 하고 싶은데, 비콘에 따라 로그를 남겨 그 기록을 바탕으로 빅데이터 처리를 할 수 있다고 해서 이 기능을 이용하고 싶은데 가능할지 궁금합니다.

    세 번째로는 비콘의 종류는 상관이 없는것인지, 비콘에 따라 구현이 다르게 되는지에 대한 궁금증입니다.

    바쁘신 와중에 질문드려 죄송합니다. 그리고 읽어주셔서 감사합니다.

  5. 1, 원하는 기능 구현 가능합니다. 미들웨어 형태의 서버가 필요하겠네요. 모바일 앱에서 비콘 신호를 받아 출석버튼을 활성화 하고 버튼 누르면 서버를 통해 출석처리하도록 요청하도록 하세요.

    2, 모바일 앱을 계속 켜놓고, (예로)1분마다 서버로 비콘과의 거리등을 전송하면 서버에서 30분이상 해당 지역에 있었는지 판단할 수 있습니다.

    3, 비콘이 아이비콘, 알트비콘 주종의 표준을 따랐다면 비콘의 종류와 관계없이 대부분의 비콘을 연동할 수 있습니다.

    비콘 연동하는 내용은 http://blog.hjf.pe.kr/384 을 참고하세요.

  6. Blog Icon
    박상우

    빠른 답변 대단히 감사드립니다. 혹시 eclipse에서도 구현할 수 있는 기능인가요? 제가 pascal어를 공부해본 적도, rad studio를 사용해본 적도 없어서 잘 할 수 있을지가 걱정이 됩니다..답변 다시한번 대단히 감사합니다. 큰 도움이 되었습니다.

  7. 개념과 구성만 잘 잡고 개발하신다면 툴(언어)가 문제가 되진 않을 것입니다.
    자바에서도 비슷한 기능을 제공하니까 살펴보시기 바랍니다.

    기회되면 델파이도 한번 관심 갖어주세요^^
    (델파이 교육과정 : http://devgear.co.kr/edu
    대학생분들은 5명까지 무료로 참석할 수 있습니다.)

  8. Blog Icon

    비밀댓글입니다

  9. 제가 테스트한 시점에 인바디 정보를 다루지 않아 정확한 내용을 모르겠습니다.

    만약, 체중계가 인바디 정보를 제공한다면,
    충분히 가져올 수 있습니다.

    위 샘플에서는 원하는 체중정보를
    프로필 > 서비스 > 특성 > 속성 > 값으로 원하는 값을 찾아서 사용한 것이기 때문에
    위 매커니즘으로 인바디 정보를 제공한다면 가져올 수 있을 것으로 보입니다.

  10. Blog Icon
    이원석

    감사합니다. 공부하는데 많은 도움이 되었습니다.
    다름이 아니오라, 여러개의 블루투스에서 동시에 값을 받아올수 있을까요?
    이를테면 체중계를 여러개 연결하여, 1번 체중계, 2번 체중계 데이터를 동시에 받는
    형태입니다.
    염치없이 질문 드려봅니다.
    감사합니다.

  11. 컴포넌트 구조 상 컴포넌트 여러개를 두고 연결하면 가능할 것으로 생각합니다.

    하지만, 직접해보시고 가능여부를 판단하는 것이 좋습니다.

iOS9의 새로운 기능인 "App transport Security" 예외 허용을 위한 Info.plist xml 수정방법

2015.10.01 13:11

이 글은 엠바카데로의 David I 블로그 글을 인용 및 참고해 작성한 글입니다. 자세한 내용은 원글을 통해서 확인하시기 바랍니다.

http://community.embarcadero.com/blogs/entry/how-to-use-custom-info-plist-xml-to-support-ios-9-s-new-app-transport-security-feature

iOS9의 App Transport Security 예외 허용하기

iOS9에서 애플은 내부적으로 HTTP 프로토콜 요청하는 응용프로그램을 제한하는 새로운 "App Transport Security" 기능을 추가했습니다. 


App Transport Security

“App Transport Security is a feature that improves the security of connections between an app and web services. The feature consists of default connection requirements that conform to best practices for secure connections. Apps can override this default behavior and turn off transport security. Transport security is available in iOS 9.0 or later, and in OS X v10.11 and later.”


간단하게 요약하면 iOS9 부터는 HTTP(암호화 되지 않은 통신)에 대해서 OS 단에서 제한을 한다는 내용입니다.


애플에서는 Info.plist를 설정해 앱에서 HTTP를 사용할 수 있도록 허용합니다. 

이 글에서는 RAD Studio에서 Info.plist 옵션을 설정하는 방법과 RAD Studio 10 시애틀 샘플소스코드 프로젝트에 대한 링크를 제공합니다.


❑ Info.plist 편집 방법

Info.plist 파일은 프로젝트를 빌드 할때마다 다시 생성됩니다. 그렇기 때문에 Info.plist 파일을 직접 편집하기 위해서는 예를들어 프로젝트의 디렉토리와 같은 위치에 Info.plist 파일을 복사 후 복사한 파일을 편집해야 합니다.

(Info.plist 파일은 iOS Device - 32 bit / 64 bit로 타겟 선택 후 프로젝트를 빌드하면 프로젝트 저장 경로의 하위에 생성됩니다.

예> \iOSDevice32\Debug\Project1.Info.plist)


복사 후 편집한 Info.plist 파일은 Project > Deployement 기능을 통해 별도로 배포해야합니다.

(이 과정은 이 글의 후반부에 다시 안내합니다.)


❑ App Transport Security 옵션 설정

옵션1. "App Transport Security" 비활성화


<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key><true/> </dict>


Info.plist 파일의 제일 마지막으로 이동 후 </dict> 태그 바로 위에 위의 코드를 추가합니다.

이 방법은 TWebBrowser, Indy HTTP 등의 컴포넌트를 사용하는 경우 앱에서 사용하는 모든 HTTP 통신에 대해 App Transport Security 기능을 해제하는 설정입니다.


옵션2. 'App Transport Security" 예외 도메인 등록


<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>appanalytics.embarcadero.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key><true/> </dict> </dict> </dict> 

Info.plist 파일의 제일 마지막으로 이동 후 </dict> 태그 바로 위에 위의 코드를 추가합니다.


이 방법은 특정 도메인(appanalytics.embarcadero.com)으로 접속하는 연결에 대해 보안이 적용되지 않은 HTTP 통신을 허용하도록 설정하는 방법입니다.



❑ Info.plist 배포 설정

앞에서 수정한 Info.plist 파일을 기본 Info.plist를 대신하도록 배포설정해야 합니다. 이 과정은 iOS Device 32 bit와 64 bit 모두에서 진행해야 합니다.(32 비트와 64비트 버전이 약간 다르다는 것을 주의)

배포 관리자(Project > Deployement)로 이동 후 편집한 Info.plist 파일을 추가(Add file)합니다.


아래 그림과 같이 기본 Info.plist 파일을 선택 해제합니다.(배포 대상에서 제외)

AppAnalytics_Info.plist_Project_Deployment

위와같이 배포 설정후 앱을 배포하면 변경된 설정의 Info.plist가 배포됩니다.

관련 링크



험프리.김현수 파이어몽키

[교육] 사물인터넷 교육

2015.09.22 09:27


모바일 개발환경 설정 : http://tech.devgear.co.kr/402210


비콘

따라하기

http://tech.devgear.co.kr/delphi_news/413402


UUID : {E2C56DB5-DFFB-48D2-B060-D0F5A71096E0}




파일배포 참고 글


스마트 조명

hue_api_lights.json


hue_api_registration.json


procedure TForm1.Button1Click(Sender: TObject);

var

  Value: TJSONValue;

  ErrNo: Integer;

begin

  RESTRequest2.Execute;


  Value := RESTResponse2.JSONValue;


  if Value.TryGetValue<Integer>('[0].error.type', ErrNo) then

  begin

    if ErrNo = 101 then

    begin

      ShowMessage('중앙의 버튼을 눌러주세요.');

      Exit;

    end;

  end;


  if Value.TryGetValue<string>('[0].success.username', FUsername) then

  begin

    ShowMessage('등록되었습니다.');

  end;

end;


procedure TForm1.FormCreate(Sender: TObject);

begin

  FUsername := 'humphreykim';

end;


procedure TForm1.Switch1Switch(Sender: TObject);

var

  onoff: string;

begin

  if Switch1.IsChecked then

    onoff := '{"on":true}'

  else

    onoff := '{"on":false}';


  RESTRequest1.Params.ParameterByName('body').Value := onoff;

  RESTRequest1.Params.ParameterByName('username').Value := FUsername;

  RESTRequest1.Execute;

end;


REST API 이해하기 : http://blog.hjf.pe.kr/462

스마트 체중계(Bluetooth LE)

const

  ScaleDeviceName = 'Wahoo';


  WEIGHT_SERVICE: TBluetoothUUID          = '{00001901-0000-1000-8000-00805F9B34FB}';

  WEIGHT_CHARACTERISTIC: TBluetoothUUID   = '{00002B01-0000-1000-8000-00805F9B34FB}';


    FBLEDevice: TBluetoothLEDevice; // Ctrl + [space]

    FBLEGattService: TBluetoothGattService;

    FBLEGattChar: TBluetoothGattCharacteristic;


따라하기

http://blog.hjf.pe.kr/404

앱테더링

따라하기

http://blog.hjf.pe.kr/279

기타

질문/답변


험프리.김현수 교육, 세미나

  1. Blog Icon

    비밀댓글입니다

  2. 안녕하세요. 지난번에 사물인터넷 교육을 들었습니다. 좋은교육 감사합니다. 다름이 아니라 지난 수업 중에 알려주셨던 헬스케어관련? 알고리즘을 볼 수 있는 사이트를 보여주셨었는데.. 그 사이트를 잊어버려서요 ㅜ 혹시 알려주실 수 있을까요?

  3. Blog Icon
    황수연

    교육 잘받았습니다. 블로그 자료가 도움이 많이 될듯 합니다.

[교육] 한국감정평가협회 데이터스냅 교육

2015.09.09 10:40

사원정보 DB

EMPLOYEE.GDB

C:\Users\Public\Documents\Embarcadero\RAD Studio\12.0\Samples\Data



새로운기능
http://www.devgear.co.kr/products/rad-studio/featurelist/


델파이 기술문서

영어 : http://docwiki.embarcadero.com/
한글 : http://devgear.co.kr/docwiki


192.168.50.19



데브기어 교육

devgear.co.kr/edu


모바일 개발환경 설정

http://tech.devgear.co.kr/402210


FireDAC 소개

http://tech.devgear.co.kr/delphi_news/410454


데이터스냅 집중해부

http://tech.devgear.co.kr/delphi_news/405345


REST Debugger

RESTDebugger.zip


tech_devgear_jsondata.json


험프리.김현수 교육, 세미나

  1. Blog Icon
    이두용

    데이타스냅 PPT 자료 올려주세요..감사합니다.

  2. 발표자료는 팀장님을 통해 받으실수 있도록 전달해 드렸습니다.

[시애틀] 안드로이드 서비스 앱을 만들 수 있습니다.

2015.09.07 11:12

안드로이드 서비스 앱을 개발하면 안드로이드 OS에서 백그라운드 작업을 실행할 수 있습니다.

안드로이드 서비스 개발

RAD Studio에서 안드로이드 서비스를 만들 수 있는 새로운 프로젝트가 추가되었습니다.

새로운 안드로이드 서비스 프로젝트에서는 다양한 종류의 서비스(로컬 서비스 및 원격 서비스 모두)를 취급하고 인텐트를 이용해 비동기 작업을 지원합니다.

안드로이드 서비스 프로젝트는 서비스 메소드와 이벤트를 만들 수 있는 데이터 모듈로 구성되며, 프로젝트를 빌드하면 선택한 서비스 종류에 따라 JAR 파일이 생성됩니다.

자세한 내용은 안드로이드 서비스와 안드로이드 서비스 만들기 문서를 참고하세요.


험프리.김현수 RAD Studio 정보