.net MAUI 에서 앱 아이콘 변경 방법

Software/C#|2025. 12. 2. 14:04
반응형

안드로이드 앱을 만들기 위해 MAUI를 이용해서 만들었습니다. 

앱을 만들고 나서 아이콘을 변경하기 위해 인터넷에 돌아 다니는 방법을 사용해서 변경했는데 왠지 기본 아이콘에서 전혀 변경이 안돼어서 몇일을 찾고 찾아서 드디어 해결을 했습니다. 

 

솔루션 탐색기에서 Platforms→Android→Resources→AndroidManifest.xml 파일을 클릭하면

애플리케이션 세부정보가 나타납니다.

애플리케이션 아이콘 항목을 아래와 같이 변경을 해 주어야만 아이콘이 변경이 됩니다.

Resources→AppIcon 위치에 원하는 이미지를 넣습니다. (예 : Icon.png)

그런후 프로젝트 파일을 엽니다. (확장자 : csproj)

아래 내용을 추가 합니다.

<!-- App Icon -->
	<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\icon.png" Color="#FFFFFF" />

그리고 다시 컴파일후에 실행하면 아이콘이 변경이 됩니다. 
반응형

댓글()

IEEE754 단정밀(32Bit) 데이타와 float 형 변수의 상호 변환 - C#

Software/C#|2025. 3. 31. 13:22
반응형

   

static class Ieee754Converter
{
    public static byte[] GetBytes(float value)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        return bytes;
    }
    public static float ToSingle(byte[] bytes)
    {
        float value = BitConverter.ToSingle(bytes, 0);
        return value;
    }
}

 

예 : +7.282600E+01  <-> {0xE9} {0xA6} {0x91} {0x42}

 

byte[ ] temp = Ieee754Converter.GetBytes(3.141592f);
float value = Ieee754Converter.ToSingle(temp);
       

반응형

댓글()

Laser Diode의 Threshold Current 계산 알고리즘 - Least Square Method - C#

반응형

 

	public double ThresholdCurrent(in double[] Current, in double[] Power, double PowerLow, double PowerHigh)
	{
		double thresholdCurrent = 0;

		try
		{
			int startIndex = Array.FindIndex(Power, x => x >= PowerLow);
			int endIndex = Array.FindIndex(Power, x => x >= PowerHigh);

			var subCurrent = Current.Skip(startIndex).Take(endIndex - startIndex + 1).ToArray();
			var subPower = Power.Skip(startIndex).Take(endIndex - startIndex + 1).ToArray();

			var (slope, intercept) = LeastSquaresFit(subCurrent, subPower);

			if(slope != 0) thresholdCurrent = -intercept / slope;            
		}
		catch
		{
			thresholdCurrent = 0 ;
		}		

		return thresholdCurrent;
	}	
	//-----------------------------------------------------------------------------------------------------------------
	private (double Slope, double Intercept) LeastSquaresFit(double[] x, double[] y)
	{
		int n = x.Length;        
        
        double sumX = x.Sum();
        double sumY = y.Sum();
        double sumXY = x.Zip(y, (xi, yi) => xi * yi).Sum();
        double sumXX = x.Select(xi => xi * xi).Sum();
        
        var Slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
        var yIntercept = (sumY - slope * sumX) / n;
		
		return (slope, yIntercept);
	}
	//-----------------------------------------------------------------------------------------------------------------
반응형

댓글()

비주얼 스튜디오(Visual Studio) WinForm 에서 폼 디자이너가 나타나지 않을 때

Developer's Story|2025. 3. 20. 15:35
반응형

비주얼 스튜디오로 만든 Winform 프로젝트를 수정할 일이 생겨서 프로젝트를 열었는데 폼 디자이너가 전혀 열리지 않는 현상이 발생했다. 인터넷을 뒤져서 이것저것 찾아 보았지만 해결을 할 수가 없었다. 

 

그러다 우연히 프로젝트가 들어있는 폴더를 밖으로 빼고 다시 불러와 보니 정상적으로 폼 디자이너가 보이기 시작했다. 

원인은 이번에 비주얼 스튜디오가 업그레이드 되면서 프로젝트 파일들이 들어있는 폴더에 ( ) 를 사용했을 경우 문제가 발생한다는 것을 알아냈다. 

 

난 프로그램 버젼을 폴더에 () 안에 표시하는데 그걸 빼고 했더니 정상 동작이 되었다. 이게 오류인지 일부러 그렇게 만든건지 모르겠다. 

하여간 아래 처럼 ( ) 제외해야 폼 디자이너가 정상적으로 나타난다. 

 

기존 폴더 : D:\TestProject(Ver 1.0.0)\   오류

수정 폴더 : D:\TestProject\                    정상

 

 

반응형

댓글()

IEEE754 단정밀(32Bit) 데이타와 float 형 변수의 상호 변환 - C++

Software/C++ Builder|2025. 3. 17. 16:05
반응형

계측기와 데이타를 주고 받는 경우 계측기에서 측정된 데이타가 ASCii 형태로 들어 오는 경우가 있다. 이럴 경우 데이타의 갯수가 짧은 경우에는 상관이 없지만 데이타 갯수가 수십 ~ 수백개가 될 경우 통신 속도문제로 데이타를 주고 받는데 시간이 많이 걸리게 된다. 

 

더군다나 ASCii 를 사용하게 되면 데이타는 더 길어질 수 밖에 없어서 시간이 더 많이 소요가 된다. 

이럴때 데이타의 길이를 줄이기 위해 계측기가 IEEE754형태의 단정밀로 변환해서 데이타를 주고 받을 수 있는 경우가 있는데 이럴경우 데이타의 길이를 1/3로 줄일 수 있다. (13byte 아스키값을 4byte 로 변형)

 

예 : +7.282600E+01  <-> {0xE9} {0xA6} {0x91} {0x42}

 

변환 방법은 간단하게 Union 사용하면 된다. 

 

union IEEE754_Float
{
    unsigned char uData[4] ;
    float fValue ;
} ;

 

 

IEEE754_Float data ;

data.fValue = 72.826 ;     // float 변수에 값을 넣으면 uData에 각각의 바이트로 자동으로 변환되어 저장

 

IEEE754_Float data ;

data. uData[0] = 0xE9 ;  // 각 바이트에 값을 넣으면 fValue 에 자동으로 변환된 float 값이 저장된다. 

data. uData[1] = 0xA6 ;

data. uData[2] = 0x91 ;

data. uData[3] = 0x42 ;

 

 

 

 

반응형

댓글()

YAML 로 프로그램 설정 데이타 저장 및 불러오기 - C#

Software/C#|2025. 3. 14. 10:07
반응형

이전에 JSON을 이용하여 제어프로그램의 Recipe 파일의 저장과 불러오기 기능에 대해 포스팅 했었다. 

그런데 조금 사용하기 불편하고 코딩량이 많아서 다른 수단을 찾다가 YAML 이 최근에 설정파일 저장용으로 많이 사용된다는 것을 보고 사용해 보았다. 코딩량도 상당히 줄었고 무엇보다 항목을 추가하거나 제거할 때 코딩에서 수정해야 하는 부분이 많이 줄어서 현재 모든 프로그램에서 사용하고 있다. 

 

1. YAML 사용하기 위해 Nuget에서 YamlDotNet 을 먼저 설치한다. 

 

2. Yaml 데이타를 저장하거나 불러오기 위한 클래스 생성 : 다양한 종류의 설정항목에 대응하기 위해 generic class 형식으로 만듦

public class YamlControl<T>
{ 
    public bool SaveYaml(string FileName, T data)
    {
        bool result = true;

        try
        {
            var serializer = new SerializerBuilder().Build().Serialize(data);

            using StreamWriter sw = new StreamWriter(FileName);
            sw.Write(serializer);
        }
        catch
        {
            result = false;    
        }

        return result;
    }

    public bool LoadYaml(string FileName, ref T objectData)
    {
        bool result = true;

        try
        {
            var yaml = File.ReadAllText(FileName);
            objectData = new DeserializerBuilder().Build().Deserialize<T>(yaml);
        }
        catch
        {
            result = false;
        }            

        return result;
    }
}

 

3. 설정항목에 대한 클래스 생성 : 아래 클래스는 프로그램에 따라 변경해야 하며 아래 내용은 예시적으로 만든 임의의 클래스 

public class RecipeInform
{
    public BurnInParam burnInParam = new BurnInParam();
    public SweepMeasParam sweepMeasParam = new SweepMeasParam();

    public class BurnInParam
    {
        public bool Measurement { get; set; }
        public double Bias { get; set; }
        public double Step { get; set; }
    }
    
    public class SweepMeasParam
    {
        public double StartCurrent { get; set; }
        public double StopCurrent { get; set; }
        public double StepCurrent { get; set; }
    }
}

 

4. 사용방법 

항목 불러오기 

YamlControl<RecipeInform> yamlControl = new YamlControl<RecipeInform>();
string filename = string.Format("{0}{1}.yaml", Global.conditionFolder, comboCondition.Text);
RecipeInform recipe = new RecipeInform();
yamlControl.LoadYaml(filename, ref recipe);


항목 저장하기 

RecipeInform recipe = new RecipeInform();
recipe.burnInParam.Measurement = checkBurnInMeas.Checked;
recipe.burnInParam.Bias = double.Parse(textBiasCurrent.Text);
recipe.burnInParam.Step = double.Parse(textBurnInStepCurrent.Text);
recipe.sweepMeasParam.StartCurrent = double.Parse(textStartCurrent.Text);
recipe.sweepMeasParam.StopCurrent = double.Parse(textStopCurrent.Text);
recipe.sweepMeasParam.StepCurrent = double.Parse(textStepCurrent.Text);


string filename = string.Format("{0}{1}.yaml", Global.conditionFolder, comboCondition.Text);
YamlControl<RecipeInform> yamlControl = new YamlControl<RecipeInform>();
yamlControl.SaveYaml(filename, recipe) ;
반응형

댓글()

Flow Meter(FML300-D SERIES) 제어 클래스 - C#

Software/C#|2025. 3. 11. 15:35
반응형

 

    public class FML300 
    {
        private readonly SerialPort commPort ;
        private readonly ModbusSerialMaster modbusSerialMaster ;

        public FML300(ModbusSerialMaster modbusSerial)
        {
            modbusSerialMaster = modbusSerial;
        }
        //---------------------------------------------------------------------------
        public FML300(SerialPort serialPort)
        {
            commPort = serialPort ;
            modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
        }
        //---------------------------------------------------------------------------
        public FML300(string portNumber)
        {
            try
            {
                commPort = new SerialPort(portNumber, 38400) ;
                commPort.Parity = Parity.None;
                commPort.StopBits = StopBits.One;
                commPort.ReadTimeout = 100;
                commPort.WriteTimeout = 100;
                commPort.Open();

                modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
            }
            catch
            {
            }
        }
        //---------------------------------------------------------------------------
        public bool InstantaneousFlowRate(byte DeviceAddress, ref double FlowRate)
        {
            bool result = true ;

            try
            {
                var buffer = modbusSerialMaster.ReadInputRegisters(DeviceAddress, 3, 1);
                FlowRate = buffer[0] ;
            }
            catch
            {
                result = false ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public bool FlowTemperature(byte DeviceAddress, ref double Temperature)
        {
            bool result = true ;    

            try
            { 
                var buffer = modbusSerialMaster.ReadInputRegisters(DeviceAddress, 4, 1) ;
                Temperature = buffer[0] ;
                if(Temperature > 6000) Temperature = 0;     // 물이 흐르지 않으면 온도가 큰값이 읽혀진다. 
            }
            catch
            {
                result = false ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public int FlowRateAndTemperature(byte DeviceAddress, ref double FlowRate, ref double Temperature)
        {
            int result = 0 ;    

            try
            { 
                var buffer = modbusSerialMaster.ReadInputRegisters(DeviceAddress, 1, 4) ;

                FlowRate = (double)buffer[1] / 100.0 ;
                Temperature = (double)buffer[2] / 10.0 ;

                if(Temperature > 6000) Temperature = 0;     // 물이 흐르지 않으면 온도가 큰값이 읽혀진다. 
            }
            catch
            {
                result = -1 ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
    }
반응형

댓글()

Chroma IT 의 UPS(Rodem Series) 제어 클래스 - C#

Software/C#|2025. 3. 11. 15:32
반응형

 

    public class RodemSeries
    {
        private SerialPort commPort;
        public double InputVoltage { get; }
        public double OutputVoltage { get; }
        public double Temperature { get; }
        public int BlackOut { get; }        // 0:No, 1:Yes
	    public int LowBattery { get; }      // 0:No, 1:Yes

        public RodemSeries(SerialPort CommPort)
        {
            commPort = CommPort;
        }
        //---------------------------------------------------------------------------
        public bool Initialize(string ModelName)
        {
            bool result = false ;
	        byte[] sendBuffer = new byte[] {(byte)'I', 0x0d} ;

            try
            {
                commPort.Write(sendBuffer, 0, sendBuffer.Length);
                Thread.Sleep(500);

                if(commPort.BytesToRead > 0)
                {
                    byte[] readBuffer = new byte[commPort.BytesToRead + 5];
                    commPort.Read(readBuffer, 0, commPort.BytesToRead);
                    string str = Encoding.Default.GetString(readBuffer);
                    result = str.Contains(ModelName);
                }
            }
            catch 
            { 
                result = false; 
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public bool ReadStatus()
        {
            bool result = true;
	        byte[] sendBuffer = new byte[] {(byte)'Q', (byte)'1', 0x0d} ;

            try
            {
                commPort.Write(sendBuffer, 0, sendBuffer.Length);
                Thread.Sleep(500);

                if(commPort.BytesToRead > 0)
                {
                    byte[] readBuffer = new byte[commPort.BytesToRead + 5];
                    commPort.Read(readBuffer, 0, commPort.BytesToRead);

                    if(readBuffer[0] != (byte)'(') result = false;
                    else
                    {
                        result = StatusInformation(readBuffer);    
                    }                    
                }
                else
                {
                    result = false;
                }
            }
            catch 
            { 
                result = false; 
            }

            return result;
        }
        //---------------------------------------------------------------------------
        private bool StatusInformation(byte[] Buffer)
        {
            bool result = true;

            try
            {
                string str = Encoding.Default.GetString(Buffer);
                string[] data = str.Split(' ');

                OutputVoltage = double.Parse(data[2]) ;
                Temperature = double.Parse(data[6]) ;

                BlackOut = Buffer[38] - 0x30;
                LowBattery = Buffer[39] - 0x30;

                if (BlackOut > 1 || BlackOut < 0) BlackOut = 0;
                if (LowBattery > 1 || LowBattery < 0) LowBattery = 0;
            }
            catch
            {
                result = false;
            }

            return result;
        }
        //---------------------------------------------------------------------------
    }
반응형

댓글()