2017-11-22 01:40:10 +01:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using NLog;
|
|
|
|
|
using NLog.Config;
|
|
|
|
|
using NLog.Targets;
|
|
|
|
|
using SixLabors.ImageSharp;
|
|
|
|
|
|
2017-11-22 02:09:13 +01:00
|
|
|
|
namespace WatchFace
|
2017-11-22 01:40:10 +01:00
|
|
|
|
{
|
|
|
|
|
internal class Program
|
|
|
|
|
{
|
|
|
|
|
private const string AppName = "WatchFace";
|
|
|
|
|
|
|
|
|
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
|
|
|
|
|
|
|
|
|
private static void Main(string[] args)
|
|
|
|
|
{
|
2017-11-22 02:09:13 +01:00
|
|
|
|
if (args.Length == 0 || args[0] == null)
|
2017-11-22 01:40:10 +01:00
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("{0} unpacks Amazfit Bip downloadable watch faces.", AppName);
|
|
|
|
|
Console.WriteLine("Usage: {0}.exe watchface.bin", AppName);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-22 02:09:13 +01:00
|
|
|
|
var inputFileName = args[0];
|
|
|
|
|
if (!File.Exists(inputFileName))
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("File '{0}' doesn't exists.", inputFileName);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Path.GetExtension(inputFileName) == "json")
|
|
|
|
|
PackWatchFace(inputFileName);
|
|
|
|
|
else
|
|
|
|
|
UnpackWatchFace(inputFileName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void PackWatchFace(string inputFileName) { }
|
|
|
|
|
|
|
|
|
|
private static void UnpackWatchFace(string inputFileName)
|
|
|
|
|
{
|
|
|
|
|
var outputDirectory = CreateOutputDirectory(inputFileName);
|
|
|
|
|
var baseName = Path.GetFileNameWithoutExtension(inputFileName);
|
|
|
|
|
SetupLogger(Path.Combine(outputDirectory, $"{baseName}.log"));
|
2017-11-22 01:40:10 +01:00
|
|
|
|
|
|
|
|
|
var reader = ReadWatchFace(inputFileName);
|
|
|
|
|
if (reader == null) return;
|
|
|
|
|
|
|
|
|
|
var watchFace = ParseResources(reader);
|
|
|
|
|
if (watchFace == null) return;
|
|
|
|
|
|
|
|
|
|
Logger.Debug("Exporting resources to '{0}'", outputDirectory);
|
|
|
|
|
ExportImages(reader, outputDirectory);
|
2017-11-22 02:09:13 +01:00
|
|
|
|
ExportConfig(watchFace, Path.Combine(outputDirectory, $"{baseName}.json"));
|
2017-11-22 01:40:10 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Reader ReadWatchFace(string inputFileName)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Opening watch face '{0}'", inputFileName);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using (var fileStream = File.OpenRead(inputFileName))
|
|
|
|
|
{
|
|
|
|
|
var reader = new Reader(fileStream);
|
|
|
|
|
Logger.Debug("Reading parameters...");
|
|
|
|
|
reader.Read();
|
|
|
|
|
return reader;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Logger.Fatal(e);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static WatchFace ParseResources(Reader reader)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Parsing parameters...");
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return WatchFace.Parse(reader.Resources);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Logger.Fatal(e);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string CreateOutputDirectory(string originalFileName)
|
|
|
|
|
{
|
|
|
|
|
var path = Path.GetDirectoryName(originalFileName);
|
|
|
|
|
var name = Path.GetFileNameWithoutExtension(originalFileName);
|
2017-11-22 02:09:13 +01:00
|
|
|
|
var unpackedPath = Path.Combine(path, $"{name}");
|
2017-11-22 01:40:10 +01:00
|
|
|
|
if (!Directory.Exists(unpackedPath)) Directory.CreateDirectory(unpackedPath);
|
|
|
|
|
return unpackedPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ExportImages(Reader reader, string outputDirectory)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Exporting images...");
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var index = 0;
|
|
|
|
|
foreach (var image in reader.Images)
|
|
|
|
|
{
|
|
|
|
|
image.Save(Path.Combine(outputDirectory, $"{index}.bmp"));
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Logger.Fatal(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-22 02:09:13 +01:00
|
|
|
|
private static void ExportConfig(WatchFace watchFace, string jsonFileName)
|
2017-11-22 01:40:10 +01:00
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Exporting config...");
|
|
|
|
|
try
|
|
|
|
|
{
|
2017-11-22 02:09:13 +01:00
|
|
|
|
using (var fileStream = File.OpenWrite(jsonFileName))
|
2017-11-22 01:40:10 +01:00
|
|
|
|
using (var writer = new StreamWriter(fileStream))
|
|
|
|
|
{
|
|
|
|
|
writer.Write(JsonConvert.SerializeObject(watchFace, Formatting.Indented,
|
|
|
|
|
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}));
|
|
|
|
|
writer.Flush();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Logger.Fatal(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-22 02:09:13 +01:00
|
|
|
|
private static void SetupLogger(string logFileName)
|
2017-11-22 01:40:10 +01:00
|
|
|
|
{
|
|
|
|
|
var config = new LoggingConfiguration();
|
2017-11-22 02:09:13 +01:00
|
|
|
|
|
|
|
|
|
var fileTarget = new FileTarget
|
|
|
|
|
{
|
|
|
|
|
FileName = logFileName,
|
|
|
|
|
Layout = "${message}"
|
|
|
|
|
};
|
|
|
|
|
config.AddTarget("file", fileTarget);
|
|
|
|
|
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, fileTarget));
|
|
|
|
|
|
|
|
|
|
var consoleTarget = new ColoredConsoleTarget
|
|
|
|
|
{Layout = @"${message}"};
|
2017-11-22 01:40:10 +01:00
|
|
|
|
config.AddTarget("console", consoleTarget);
|
2017-11-22 02:09:13 +01:00
|
|
|
|
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
|
|
|
|
|
|
2017-11-22 01:40:10 +01:00
|
|
|
|
LogManager.Configuration = config;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|